ContactsProvider2.java revision 7cf50494501938f175d288077145acf49da8f171
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; 139916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikovimport android.provider.ContactsContract.SearchSnippetColumns; 1403de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 14182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 1423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmannimport android.provider.ContactsContract.StreamItemPhotos; 143f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport android.provider.ContactsContract.StreamItems; 14497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.LiveFolders; 14597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.OpenableColumns; 14697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.SyncStateContract; 147a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 1489a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikovimport android.telephony.TelephonyManager; 149a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 150c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1514f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 152108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawaimport java.io.BufferedWriter; 153d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 154f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport java.io.File; 155b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 156d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 157d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 158108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawaimport java.io.OutputStreamWriter; 159108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawaimport java.io.Writer; 16042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.text.SimpleDateFormat; 1617e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 16246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawaimport java.util.Arrays; 1635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 16442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.util.Date; 165b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1660e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 168622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 169b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1700e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 171ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1724f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 1775b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanapublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener { 178caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 179bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 180bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 181bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 18315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_INITIALIZE = 0; 18415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_OPEN_WRITE_ACCESS = 1; 18515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS = 2; 18615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_ACCOUNTS = 3; 18715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_LOCALE = 4; 18815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM = 5; 18905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_SEARCH_INDEX = 6; 19005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_PROVIDER_STATUS = 7; 19105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_DIRECTORIES = 8; 19205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_CHANGE_LOCALE = 9; 193f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int BACKGROUND_TASK_CLEANUP_PHOTOS = 10; 194619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** Limit for the maximum number of social stream items to store under a raw contact. */ 1993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int MAX_STREAM_ITEMS_PER_RAW_CONTACT = 5; 2003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 201f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** Rate limit (in ms) for photo cleanup. Do it at most once per day. */ 202f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int PHOTO_CLEANUP_RATE_LIMIT = 24 * 60 * 60 * 1000; 203f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 2043d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 205b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov * Property key for the legacy contact import version. The need for a version 2063d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 2073d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 2083d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 209b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final String PROPERTY_CONTACTS_IMPORTED = "contacts_imported_v1"; 210b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final int PROPERTY_CONTACTS_IMPORT_VERSION = 1; 21151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov private static final String PREF_LOCALE = "locale"; 2123d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2130dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static final String PROPERTY_AGGREGATION_ALGORITHM = "aggregation_v2"; 2140dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static final int PROPERTY_AGGREGATION_ALGORITHM_VERSION = 2; 2150dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 2160e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 2170e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 2185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final ProfileAwareUriMatcher sUriMatcher = 2195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ProfileAwareUriMatcher(UriMatcher.NO_MATCH); 2204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2212f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa /** 2222f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa * Used to insert a column into strequent results, which enables SQL to sort the list using 2232f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa * the total times contacted. See also {@link #sStrequentFrequentProjectionMap}. 2242f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa */ 2252f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa private static final String TIMES_USED_SORT_COLUMN = "times_used_sort"; 2265e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 227d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 2282f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa + TIMES_USED_SORT_COLUMN + " DESC, " 2299b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 230d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 231d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 232d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 233d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 23445ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa private static final String FREQUENT_ORDER_BY = DataUsageStatColumns.TIMES_USED + " DESC," 23545ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 23645ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa 2376e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_CONTACTS_TABLE = 2389b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.CONTACTS + " SET " + Contacts.TIMES_CONTACTED + "=" + 2399b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + Contacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 2409b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + Contacts.TIMES_CONTACTED + " + 1) END WHERE " + Contacts._ID + "=?"; 2419b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 2426e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE = 2439b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.RAW_CONTACTS + " SET " + RawContacts.TIMES_CONTACTED + "=" + 2449b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + RawContacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 2459b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + RawContacts.TIMES_CONTACTED + " + 1) END WHERE " + RawContacts.CONTACT_ID + "=?"; 2469b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 247de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa /* package */ static final String PHONEBOOK_COLLATOR_NAME = "PHONEBOOK"; 248de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa 2493716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Regex for splitting query strings - we split on any group of non-alphanumeric characters, 2503716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // excluding the @ symbol. 2513716f1447ceb21180d1301790eabd8b9453f486dDave Santoro /* package */ static final String QUERY_TOKENIZER_REGEX = "[^\\w@]+"; 2523716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 253d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 254d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 2555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 2565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 257a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_DATA = 1004; 2585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 2595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 2605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 2615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 262a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_PHOTO = 1009; 263f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_ID_DISPLAY_PHOTO = 1010; 264f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_LOOKUP_DISPLAY_PHOTO = 1011; 265f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_LOOKUP_ID_DISPLAY_PHOTO = 1012; 266f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_AS_VCARD = 1013; 267f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_AS_MULTI_VCARD = 1014; 268f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_LOOKUP_DATA = 1015; 269f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_LOOKUP_ID_DATA = 1016; 270f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_ID_ENTITIES = 1017; 271f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_LOOKUP_ENTITIES = 1018; 272f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_LOOKUP_ID_ENTITIES = 1019; 273f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_ID_STREAM_ITEMS = 1020; 274f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_LOOKUP_STREAM_ITEMS = 1021; 275f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_LOOKUP_ID_STREAM_ITEMS = 1022; 27645ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa private static final int CONTACTS_FREQUENT = 1023; 2774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 2795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 2805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 28146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 282f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int RAW_CONTACTS_ID_DISPLAY_PHOTO = 2006; 283f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int RAW_CONTACTS_ID_STREAM_ITEMS = 2007; 28482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro private static final int RAW_CONTACTS_ID_STREAM_ITEMS_ID = 2008; 2854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2866bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 2876bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 288ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 28948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 29048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 29148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 29248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 29348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 29448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 29548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 29648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 297a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2986bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 2996bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 300b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 301b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 302b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 30382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 30482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 3051f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 30631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 30731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 308eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 309eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 310ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 311ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 312ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 313ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 31435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 315b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 3165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final int PROFILE_SYNCSTATE = 11002; 3175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final int PROFILE_SYNCSTATE_ID = 11003; 31835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 319c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 320c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 321c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3221b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 3231b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 3241b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 3251b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 3261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 32746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 32846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 32909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private static final int PROVIDER_STATUS = 16001; 33009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 331d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES = 17001; 332d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES_ID = 17002; 333d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3347a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private static final int COMPLETE_NAME = 18000; 3357a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 33624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE = 19000; 33724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_ENTITIES = 19001; 33824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_DATA = 19002; 33924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_DATA_ID = 19003; 34024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_AS_VCARD = 19004; 34124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS = 19005; 34224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID = 19006; 34324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID_DATA = 19007; 34424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID_ENTITIES = 19008; 3455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final int PROFILE_STATUS_UPDATES = 19009; 3463202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro private static final int PROFILE_RAW_CONTACT_ENTITIES = 19010; 34724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 34846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final int DATA_USAGE_FEEDBACK_ID = 20001; 34946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 3503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS = 21000; 3513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_PHOTOS = 21001; 3523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID = 21002; 3533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID_PHOTOS = 21003; 3543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID_PHOTOS_ID = 21004; 3553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_LIMIT = 21005; 3563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 357f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int DISPLAY_PHOTO = 22000; 358f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int PHOTO_DIMENSIONS = 22001; 359f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 3605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Inserts into URIs in this map will direct to the profile database if the parent record's 3615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // value (looked up from the ContentValues object with the key specified by the value in this 3625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // map) is in the profile ID-space (see {@link ProfileDatabaseHelper#PROFILE_ID_SPACE}). 3635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final Map<Integer, String> INSERT_URI_ID_VALUE_MAP = Maps.newHashMap(); 3645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro static { 3655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(DATA, Data.RAW_CONTACT_ID); 3665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(RAW_CONTACTS_DATA, Data.RAW_CONTACT_ID); 3675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STATUS_UPDATES, StatusUpdates.DATA_ID); 3685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STREAM_ITEMS, StreamItems.RAW_CONTACT_ID); 3695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(RAW_CONTACTS_ID_STREAM_ITEMS, StreamItems.RAW_CONTACT_ID); 3705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STREAM_ITEMS_PHOTOS, StreamItemPhotos.STREAM_ITEM_ID); 3715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STREAM_ITEMS_ID_PHOTOS, StreamItemPhotos.STREAM_ITEM_ID); 3725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 3735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 374dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID = 375dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 376dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME 377dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 378dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE 37943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + "=" + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AND (" 38043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET 38143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + "=" + RawContactsColumns.CONCRETE_DATA_SET + " OR " 38243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET + " IS NULL AND " 38343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_DATA_SET + " IS NULL)" 384dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND " + Groups.FAVORITES + " != 0"; 385dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 386dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID = 387dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 388dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 389dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 390dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 39143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AND (" 39243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET + "=" 39343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_DATA_SET + " OR " 39443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET + " IS NULL AND " 39543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_DATA_SET + " IS NULL)" 39643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + " AND " + Groups.AUTO_ADD + " != 0"; 397dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 398dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String[] PROJECTION_GROUP_ID 399dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana = new String[]{Tables.GROUPS + "." + Groups._ID}; 400dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 401dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_GROUPMEMBERSHIP_DATA = DataColumns.MIMETYPE_ID + "=? " 402dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.GROUP_ROW_ID + "=? " 403dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.RAW_CONTACT_ID + "=?"; 404dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 405dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_STARRED_FROM_RAW_CONTACTS = 406dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana "SELECT " + RawContacts.STARRED 407dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?"; 408dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 409d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 410f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 411f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 412f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 41367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 41467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 4156cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 4166802030a777c0c3ba1dc029c534cca4784260632Dave Santoro RawContactsColumns.CONCRETE_ACCOUNT_TYPE, 4176802030a777c0c3ba1dc029c534cca4784260632Dave Santoro RawContactsColumns.CONCRETE_ACCOUNT_NAME, 41843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContactsColumns.CONCRETE_DATA_SET, 4193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 420f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 421ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 422ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 423d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 4246802030a777c0c3ba1dc029c534cca4784260632Dave Santoro public static final int ACCOUNT_TYPE = 1; 4256802030a777c0c3ba1dc029c534cca4784260632Dave Santoro public static final int ACCOUNT_NAME = 2; 42643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro public static final int DATA_SET = 3; 42743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro public static final int DATA_ID = 4; 42843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro public static final int CONTACT_ID = 5; 429ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4301f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 431f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov interface RawContactsQuery { 43219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 43319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 43419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 435ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.DELETED, 436ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 437ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_NAME, 43843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.DATA_SET, 43919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 44019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 44119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 442ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_TYPE = 1; 443ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_NAME = 2; 44443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int DATA_SET = 3; 44519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 44619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 447c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 448caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 44971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 45071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 45171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 45271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 45371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 45471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 45571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 45671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 4577cf50494501938f175d288077145acf49da8f171Daniel Lehmann + " WHERE " + DataColumns.MIMETYPE_ID + "=?" 4587cf50494501938f175d288077145acf49da8f171Daniel Lehmann + " AND " + GroupMembership.GROUP_ROW_ID + "=" 45971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 46071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 46171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 46271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 463a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating DIRTY flag on multiple raw contacts */ 464a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_DIRTY_SQL = 465a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 466a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.DIRTY + "=1" + 467a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 468a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 469a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating VERSION on multiple raw contacts */ 470a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_VERSION_SQL = 471a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 472a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + 473a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 474a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 475c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov // Current contacts - those contacted within the last 3 days (in seconds) 476c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final long EMAIL_FILTER_CURRENT = 3 * 24 * 60 * 60; 477c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 478c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov // Recent contacts - those contacted within the last 30 days (in seconds) 479c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final long EMAIL_FILTER_RECENT = 30 * 24 * 60 * 60; 480c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 481f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa private static final String TIME_SINCE_LAST_USED = 482f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa "(strftime('%s', 'now') - " + DataUsageStatColumns.LAST_TIME_USED + "/1000)"; 483f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa 484c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov /* 485c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * Sorting order for email address suggestions: first starred, then the rest. 4862262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * second in_visible_group, then the rest. 4872262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * Within the four (starred/unstarred, in_visible_group/not-in_visible_group) groups 4882262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * - three buckets: very recently contacted, then fairly 489c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * recently contacted, then the rest. Within each of the bucket - descending count 49046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * of times contacted (both for data row and for contact row). If all else fails, alphabetical. 49146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * (Super)primary email address is returned before other addresses for the same contact. 492c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov */ 493c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final String EMAIL_FILTER_SORT_ORDER = 4942262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa Contacts.STARRED + " DESC, " 4952262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa + Contacts.IN_VISIBLE_GROUP + " DESC, " 496f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa + "(CASE WHEN " + TIME_SINCE_LAST_USED + " < " + EMAIL_FILTER_CURRENT 49746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " THEN 0 " 498f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa + " WHEN " + TIME_SINCE_LAST_USED + " < " + EMAIL_FILTER_RECENT 49946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " THEN 1 " 50046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " ELSE 2 END), " 50146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + DataUsageStatColumns.TIMES_USED + " DESC, " 50246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + Contacts.DISPLAY_NAME + ", " 50346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + Data.CONTACT_ID + ", " 504c591cc2ffecdd0038f787a133606752752294c13Daisuke Miyakawa + Data.IS_SUPER_PRIMARY + " DESC, " 505c591cc2ffecdd0038f787a133606752752294c13Daisuke Miyakawa + Data.IS_PRIMARY + " DESC"; 50646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 50746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** Currently same as {@link #EMAIL_FILTER_SORT_ORDER} */ 50846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final String PHONE_FILTER_SORT_ORDER = EMAIL_FILTER_SORT_ORDER; 509c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 510916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Name lookup types used for contact filtering */ 511916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final String CONTACT_LOOKUP_NAME_TYPES = 512916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_COLLATION_KEY + "," + 513916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME + "," + 51492ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov NameLookupType.NICKNAME; 515916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 516f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov /** 517f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov * If any of these columns are used in a Data projection, there is no point in 518f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov * using the DISTINCT keyword, which can negatively affect performance. 519f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov */ 520f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov private static final String[] DISTINCT_DATA_PROHIBITING_COLUMNS = { 521f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data._ID, 522f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data.RAW_CONTACT_ID, 523f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data.NAME_RAW_CONTACT_ID, 524f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 525f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 52643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.DATA_SET, 52743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 528f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.DIRTY, 529f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.NAME_VERIFIED, 530f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.SOURCE_ID, 531f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.VERSION, 532f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov }; 533916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 534f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsColumns = ProjectionMap.builder() 535f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CUSTOM_RINGTONE) 536f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME) 537f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_ALTERNATIVE) 538f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_SOURCE) 539f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.IN_VISIBLE_GROUP) 540f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LAST_TIME_CONTACTED) 541f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LOOKUP_KEY) 542f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME) 543f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME_STYLE) 544f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHOTO_ID) 545f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .add(Contacts.PHOTO_FILE_ID) 5463d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(Contacts.PHOTO_URI) 5473d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(Contacts.PHOTO_THUMBNAIL_URI) 548f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SEND_TO_VOICEMAIL) 549f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_ALTERNATIVE) 550f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_PRIMARY) 551f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.STARRED) 552f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.TIMES_CONTACTED) 553cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 554f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 555f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 556f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsPresenceColumns = ProjectionMap.builder() 557f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 558f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE) 559f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 560f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 561f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 562f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 563f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 564f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 565f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 566f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 567f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 568f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 569f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 570f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 571f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 572f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 573f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSnippetColumns = ProjectionMap.builder() 57403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov .add(SearchSnippetColumns.SNIPPET) 575f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 576f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 577f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactColumns = ProjectionMap.builder() 578f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_NAME) 579f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_TYPE) 58043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(RawContacts.DATA_SET) 58143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(RawContacts.ACCOUNT_TYPE_AND_DATA_SET) 582f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DIRTY) 583f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.NAME_VERIFIED) 584f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SOURCE_ID) 585f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.VERSION) 586f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 587f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 588f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactSyncColumns = ProjectionMap.builder() 589f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC1) 590f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC2) 591f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC3) 592f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC4) 593f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 594f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 595f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataColumns = ProjectionMap.builder() 596f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA1) 597f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA2) 598f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA3) 599f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA4) 600f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA5) 601f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA6) 602f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA7) 603f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA8) 604f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA9) 605f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA10) 606f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA11) 607f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA12) 608f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA13) 609f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA14) 610f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA15) 611f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA_VERSION) 612f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_PRIMARY) 613f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_SUPER_PRIMARY) 614f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.MIMETYPE) 615f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RES_PACKAGE) 616f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC1) 617f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC2) 618f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC3) 619f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC4) 620f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(GroupMembership.GROUP_SOURCE_ID) 621f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 622f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 623f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactPresenceColumns = ProjectionMap.builder() 624f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 625f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.PRESENCE) 626f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 627f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.CHAT_CAPABILITY) 628f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 629f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 630f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 631f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 632f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 633f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 634f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 635f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 636f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 637f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 638f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 639f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 640f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataPresenceColumns = ProjectionMap.builder() 641f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.PRESENCE, Tables.PRESENCE + "." + StatusUpdates.PRESENCE) 642f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CHAT_CAPABILITY, Tables.PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 643f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS, StatusUpdatesColumns.CONCRETE_STATUS) 644f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_TIMESTAMP, StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 645f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_RES_PACKAGE, StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 646f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_LABEL, StatusUpdatesColumns.CONCRETE_STATUS_LABEL) 647f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_ICON, StatusUpdatesColumns.CONCRETE_STATUS_ICON) 648f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 649f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 650038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 651f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sCountProjectionMap = ProjectionMap.builder() 652f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(BaseColumns._COUNT, "COUNT(*)") 653f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 654f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 655e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 656f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionMap = ProjectionMap.builder() 657f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts._ID) 658f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 659f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.NAME_RAW_CONTACT_ID) 66024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(Contacts.IS_USER_PROFILE) 661f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 662f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsPresenceColumns) 663f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 664f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 665916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Contains just the contacts columns */ 666f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionWithSnippetMap = ProjectionMap.builder() 667f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 668f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sSnippetColumns) 669f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 670916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 6715e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 672f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentStarredProjectionMap = ProjectionMap.builder() 673f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 6742f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, String.valueOf(Long.MAX_VALUE)) 675f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 676f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 677f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentFrequentProjectionMap = ProjectionMap.builder() 678f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 6792f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, "SUM(" + DataUsageStatColumns.CONCRETE_TIMES_USED + ")") 680f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 681f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 6824928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa /** 6834928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * Used for Strequent Uri with {@link ContactsContract#STREQUENT_PHONE_ONLY}, which allows 6844928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * users to obtain part of Data columns. Right now Starred part just returns NULL for 6854928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * those data columns (frequent part should return real ones in data table). 6864928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa **/ 6874928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa private static final ProjectionMap sStrequentPhoneOnlyStarredProjectionMap 6884928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa = ProjectionMap.builder() 6894928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .addAll(sContactsProjectionMap) 6904928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, String.valueOf(Long.MAX_VALUE)) 6914928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.NUMBER, "NULL") 6924928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.TYPE, "NULL") 6934928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.LABEL, "NULL") 6944928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .build(); 6954928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 6964928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa /** 6974928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * Used for Strequent Uri with {@link ContactsContract#STREQUENT_PHONE_ONLY}, which allows 6984928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * users to obtain part of Data columns. We hard-code {@link Contacts#IS_USER_PROFILE} to NULL, 6994928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * because sContactsProjectionMap specifies a field that doesn't exist in the view behind the 7004928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * query that uses this projection map. 7014928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa **/ 7024928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa private static final ProjectionMap sStrequentPhoneOnlyFrequentProjectionMap 7034928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa = ProjectionMap.builder() 7044928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .addAll(sContactsProjectionMap) 7054928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, DataUsageStatColumns.CONCRETE_TIMES_USED) 7064928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.NUMBER) 7074928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.TYPE) 7084928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.LABEL) 7094928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Contacts.IS_USER_PROFILE, "NULL") 7104928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .build(); 7114928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 712f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 713f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsVCardProjectionMap = ProjectionMap.builder() 714fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen .add(Contacts._ID) 715f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME + " || '.vcf'") 716f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.SIZE, "NULL") 717f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 718f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 719ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 720f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactsProjectionMap = ProjectionMap.builder() 721f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 722f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 723f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 724f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_PRIMARY) 725f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_ALTERNATIVE) 726f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_SOURCE) 727f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME) 728f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME_STYLE) 729f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_PRIMARY) 730f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_ALTERNATIVE) 731f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.TIMES_CONTACTED) 732f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.LAST_TIME_CONTACTED) 733f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CUSTOM_RINGTONE) 734f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SEND_TO_VOICEMAIL) 735f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 736f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.AGGREGATION_MODE) 73724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 738f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 739f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 740f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 741f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 742a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the raw entity view*/ 743f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawEntityProjectionMap = ProjectionMap.builder() 744f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 745f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 746f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.Entity.DATA_ID) 747f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 748f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 74924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 750f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 751f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 752f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 753f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 754f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 755a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the contact entity view*/ 756f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sEntityProjectionMap = ProjectionMap.builder() 757f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity._ID) 758f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.CONTACT_ID) 759f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.RAW_CONTACT_ID) 760f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DATA_ID) 761f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.NAME_RAW_CONTACT_ID) 762f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DELETED) 76324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(Contacts.IS_USER_PROFILE) 764f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 765f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 766f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 767f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 768f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 769f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 770f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 771f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 773f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataProjectionMap = ProjectionMap.builder() 774f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID) 775f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RAW_CONTACT_ID) 776f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CONTACT_ID) 777f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.NAME_RAW_CONTACT_ID) 77824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 779f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 780f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 781f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 782f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 783f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 784f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 785f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 787f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDistinctDataProjectionMap = ProjectionMap.builder() 788f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID, "MIN(" + Data._ID + ")") 789f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 79024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 791f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 792f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 793f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 794f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 795f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 796f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7979261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 798f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sPhoneLookupProjectionMap = ProjectionMap.builder() 799f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup._ID, "contacts_view." + Contacts._ID) 800f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LOOKUP_KEY, "contacts_view." + Contacts.LOOKUP_KEY) 801f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.DISPLAY_NAME, "contacts_view." + Contacts.DISPLAY_NAME) 802f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LAST_TIME_CONTACTED, "contacts_view." + Contacts.LAST_TIME_CONTACTED) 803f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TIMES_CONTACTED, "contacts_view." + Contacts.TIMES_CONTACTED) 804f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.STARRED, "contacts_view." + Contacts.STARRED) 805f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.IN_VISIBLE_GROUP, "contacts_view." + Contacts.IN_VISIBLE_GROUP) 806f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.PHOTO_ID, "contacts_view." + Contacts.PHOTO_ID) 8073d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(PhoneLookup.PHOTO_URI, "contacts_view." + Contacts.PHOTO_URI) 8083d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(PhoneLookup.PHOTO_THUMBNAIL_URI, "contacts_view." + Contacts.PHOTO_THUMBNAIL_URI) 809f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.CUSTOM_RINGTONE, "contacts_view." + Contacts.CUSTOM_RINGTONE) 810f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.HAS_PHONE_NUMBER, "contacts_view." + Contacts.HAS_PHONE_NUMBER) 811f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.SEND_TO_VOICEMAIL, "contacts_view." + Contacts.SEND_TO_VOICEMAIL) 812f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.NUMBER, Phone.NUMBER) 813f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TYPE, Phone.TYPE) 814f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LABEL, Phone.LABEL) 8152530512f639c4979fd7371c7dd25dd67e8118124Bai Tao .add(PhoneLookup.NORMALIZED_NUMBER, Phone.NORMALIZED_NUMBER) 816f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 817f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 818ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 819f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsProjectionMap = ProjectionMap.builder() 820f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups._ID) 821f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_NAME) 822f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_TYPE) 82343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(Groups.DATA_SET) 82443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(Groups.ACCOUNT_TYPE_AND_DATA_SET) 825f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SOURCE_ID) 826f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DIRTY) 827f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.VERSION) 828f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.RES_PACKAGE) 829f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE) 830f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE_RES) 831f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.GROUP_VISIBLE) 832f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYSTEM_ID) 833f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DELETED) 834f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.NOTES) 835f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SHOULD_SYNC) 836f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.FAVORITES) 837f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.AUTO_ADD) 838c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov .add(Groups.GROUP_IS_READ_ONLY) 839f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC1) 840f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC2) 841f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC3) 842f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC4) 843f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 844f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 845ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 846f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsSummaryProjectionMap = ProjectionMap.builder() 847f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sGroupsProjectionMap) 848f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_COUNT, 849f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa "(SELECT COUNT(" + ContactsColumns.CONCRETE_ID + ") FROM " 850f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Tables.CONTACTS_JOIN_RAW_CONTACTS_DATA_FILTERED_BY_GROUPMEMBERSHIP 851f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + ")") 852f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_WITH_PHONES, 853f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa "(SELECT COUNT(" + ContactsColumns.CONCRETE_ID + ") FROM " 854f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Tables.CONTACTS_JOIN_RAW_CONTACTS_DATA_FILTERED_BY_GROUPMEMBERSHIP 855f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " WHERE " + Contacts.HAS_PHONE_NUMBER + ")") 856f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa .build(); 857f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa 858f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa // This is only exposed as hidden API for the contacts app, so we can be very specific in 859f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa // the filtering 860f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa private static final ProjectionMap sGroupsSummaryProjectionMapWithGroupCountPerAccount = 861f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa ProjectionMap.builder() 862f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa .addAll(sGroupsSummaryProjectionMap) 863f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa .add(Groups.SUMMARY_GROUP_COUNT_PER_ACCOUNT, 864f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa "(SELECT COUNT(*) FROM " + Views.GROUPS + " WHERE " 865f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + "(" + Groups.ACCOUNT_NAME + "=" 866f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + GroupsColumns.CONCRETE_ACCOUNT_NAME 867f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " AND " 868f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.ACCOUNT_TYPE + "=" + GroupsColumns.CONCRETE_ACCOUNT_TYPE 869f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " AND " 870f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.DELETED + "=0 AND " 871f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.FAVORITES + "=0 AND " 872f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.AUTO_ADD + "=0" 873f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + ")" 874f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " GROUP BY " 875f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.ACCOUNT_NAME + ", " + Groups.ACCOUNT_TYPE 876f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + ")") 877f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 878f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 879373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 880f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sAggregationExceptionsProjectionMap = ProjectionMap.builder() 881f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id") 882f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.TYPE) 883f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID1) 884f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID2) 885f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 886f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 887eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 888f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSettingsProjectionMap = ProjectionMap.builder() 889f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_NAME) 890f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_TYPE) 891f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro .add(Settings.DATA_SET) 892f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_VISIBLE) 893f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.SHOULD_SYNC) 894f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ANY_UNSYNCED, 895f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 896f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ",(SELECT " 897f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "(CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL" 898f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 899f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE MIN(" + Groups.SHOULD_SYNC + ")" 900f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)" 901f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.GROUPS 902f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 903f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + SettingsColumns.CONCRETE_ACCOUNT_NAME 904f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 905f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + SettingsColumns.CONCRETE_ACCOUNT_TYPE 906f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + " AND ((" + GroupsColumns.CONCRETE_DATA_SET + " IS NULL AND " 907f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + SettingsColumns.CONCRETE_DATA_SET + " IS NULL) OR (" 908f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + GroupsColumns.CONCRETE_DATA_SET + "=" 909f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + SettingsColumns.CONCRETE_DATA_SET + "))))=0" 910f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 911f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE 0" 912f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)") 913f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_COUNT, 914f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 915f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 916f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 917f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 918f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 919f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 920f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_WITH_PHONES, 921f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 922f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 923f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 924f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Contacts.HAS_PHONE_NUMBER 925f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 926f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 927f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 928f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 929f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 93082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 931f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStatusUpdatesProjectionMap = ProjectionMap.builder() 932f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PresenceColumns.RAW_CONTACT_ID) 933f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.DATA_ID, DataColumns.CONCRETE_ID) 934f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_ACCOUNT) 935f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_HANDLE) 936f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PROTOCOL) 937f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 938f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // properly enforce uniqueness of null values 939f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CUSTOM_PROTOCOL, 940f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL + "=''" 941f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN NULL" 942f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END)") 943f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PRESENCE) 944f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CHAT_CAPABILITY) 945f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS) 946f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_TIMESTAMP) 947f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_RES_PACKAGE) 948f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_ICON) 949f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_LABEL) 950f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 951f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 9523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** Contains StreamItems columns */ 9533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final ProjectionMap sStreamItemsProjectionMap = ProjectionMap.builder() 9549b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems._ID) 9559b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.CONTACT_ID) 956af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann .add(StreamItems.CONTACT_LOOKUP_KEY) 9579b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.ACCOUNT_NAME) 9589b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.ACCOUNT_TYPE) 9599b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.DATA_SET) 9603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RAW_CONTACT_ID) 9619b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.RAW_CONTACT_SOURCE_ID) 9623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_PACKAGE) 9633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_ICON) 9643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_LABEL) 9653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.TEXT) 9663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.TIMESTAMP) 9673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.COMMENTS) 9680bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC1) 9690bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC2) 9700bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC3) 9710bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC4) 9723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .build(); 9733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 9743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final ProjectionMap sStreamItemPhotosProjectionMap = ProjectionMap.builder() 9753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos._ID, StreamItemPhotosColumns.CONCRETE_ID) 9763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RAW_CONTACT_ID) 9770bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.RAW_CONTACT_SOURCE_ID, RawContactsColumns.CONCRETE_SOURCE_ID) 9783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos.STREAM_ITEM_ID) 9793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos.SORT_INDEX) 9806802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .add(StreamItemPhotos.PHOTO_FILE_ID) 9816802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .add(StreamItemPhotos.PHOTO_URI, 9826802030a777c0c3ba1dc029c534cca4784260632Dave Santoro "'" + DisplayPhoto.CONTENT_URI + "'||'/'||" + StreamItemPhotos.PHOTO_FILE_ID) 9831dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro .add(PhotoFiles.HEIGHT) 9841dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro .add(PhotoFiles.WIDTH) 9851dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro .add(PhotoFiles.FILESIZE) 9860bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC1) 9870bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC2) 9880bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC3) 9890bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC4) 9903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .build(); 9913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 9921b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 993f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sLiveFoldersProjectionMap = ProjectionMap.builder() 994f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(LiveFolders._ID, Contacts._ID) 995f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(LiveFolders.NAME, Contacts.DISPLAY_NAME) 996f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 997f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // for contacts without a photo 998f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // .add(LiveFolders.ICON_BITMAP, Photos.DATA) 999f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 1000f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 1001d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** Contains {@link Directory} columns */ 1002f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDirectoryProjectionMap = ProjectionMap.builder() 1003f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory._ID) 1004f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.PACKAGE_NAME) 1005f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.TYPE_RESOURCE_ID) 1006f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DISPLAY_NAME) 1007f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DIRECTORY_AUTHORITY) 1008f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_TYPE) 1009f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_NAME) 1010f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.EXPORT_SUPPORT) 1011778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov .add(Directory.SHORTCUT_SUPPORT) 1012778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov .add(Directory.PHOTO_SUPPORT) 1013f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 10147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 10159705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // where clause to update the status_updates table 10169705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 10179705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 10189705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 10199705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 10209705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 10212526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private static final String[] EMPTY_STRING_ARRAY = new String[0]; 10222526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 1023bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1024bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Notification ID for failure to import contacts. 1025bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1026bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private static final int LEGACY_IMPORT_FAILED_NOTIFICATION = 1; 102751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 102803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_START_MATCH = "["; 102903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_END_MATCH = "]"; 103003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_ELLIPSIS = "..."; 103103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final int DEFAULT_SNIPPET_ARG_MAX_TOKENS = -10; 103203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 10339a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov private boolean sIsPhoneInitialized; 10349a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov private boolean sIsPhone; 10359a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 1036f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 10371129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 10381129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs2 = new String[2]; 10392526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private ArrayList<String> mSelectionArgs = Lists.newArrayList(); 10402526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 1041f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private Account mAccount; 1042f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 104346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 104446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Stores mapping from type Strings exposed via {@link DataUsageFeedback} to 104546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * type integers in {@link DataUsageStatColumns}. 104646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 104746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final Map<String, Integer> sDataUsageTypeMap; 104846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 10494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 10504f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 1051a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 1052d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 1053d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 1054a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_ID_DATA); 1055a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/entities", CONTACTS_ID_ENTITIES); 10563653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 10573653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 10582d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 10592d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 1060a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_ID_PHOTO); 1061f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/display_photo", 1062f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro CONTACTS_ID_DISPLAY_PHOTO); 10633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/stream_items", 10643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_ID_STREAM_ITEMS); 1065c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter", CONTACTS_FILTER); 10665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 10675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 10682149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/data", CONTACTS_LOOKUP_DATA); 10695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 10702149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/data", 10712149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov CONTACTS_LOOKUP_ID_DATA); 1072f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/display_photo", 1073f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro CONTACTS_LOOKUP_DISPLAY_PHOTO); 1074f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/display_photo", 1075f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro CONTACTS_LOOKUP_ID_DISPLAY_PHOTO); 1076a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/entities", 1077a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ENTITIES); 1078a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/entities", 1079a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ID_ENTITIES); 10803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/stream_items", 10813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_LOOKUP_STREAM_ITEMS); 10823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/stream_items", 10833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_LOOKUP_ID_STREAM_ITEMS); 1084f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 108542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_multi_vcard/*", 108642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann CONTACTS_AS_MULTI_VCARD); 10875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 1088ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 1089ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 10905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 109145ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa matcher.addURI(ContactsContract.AUTHORITY, "contacts/frequent", CONTACTS_FREQUENT); 10923653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 10935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 10945ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 10955ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 1096f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/display_photo", 1097f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro RAW_CONTACTS_ID_DISPLAY_PHOTO); 109846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 10993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/stream_items", 11003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann RAW_CONTACTS_ID_STREAM_ITEMS); 110182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/stream_items/#", 110282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro RAW_CONTACTS_ID_STREAM_ITEMS_ID); 110346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 110446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 1105b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 11064f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 11074f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 1108ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 110948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 11105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 1111ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 11124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 111348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 11141dac83b8fa58944acfd00f44e717a7dddc659d2dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup", EMAILS_LOOKUP); 11155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 11165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 11174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 1118ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 111948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 112046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** "*" is in CSV form with data ids ("123,456,789") */ 112146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa matcher.addURI(ContactsContract.AUTHORITY, "data/usagefeedback/*", DATA_USAGE_FEEDBACK_ID); 11221f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1123ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 1124ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 1125ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 1126ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 112735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 1128b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 1129b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 11305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/" + SyncStateContentProviderHelper.PATH, 11315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROFILE_SYNCSTATE); 11325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, 11335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro "profile/" + SyncStateContentProviderHelper.PATH + "/#", 11345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROFILE_SYNCSTATE_ID); 113535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1136a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 1137b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 1138b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 1139b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 1140b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 11414f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1142eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 1143eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 114482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 114582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 11461f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1147c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 1148c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 1149c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 1150c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 11512d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", 1152c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 1153c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 11541b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 11551b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 11561b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 11571b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 11581b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 11591b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 11601b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 11611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 116209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 116309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "provider_status", PROVIDER_STATUS); 1164d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 1165d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories", DIRECTORIES); 1166d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories/#", DIRECTORIES_ID); 11677a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 11687a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "complete_name", COMPLETE_NAME); 116924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 117024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile", PROFILE); 117124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/entities", PROFILE_ENTITIES); 117224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/data", PROFILE_DATA); 117324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/data/#", PROFILE_DATA_ID); 117424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/as_vcard", PROFILE_AS_VCARD); 117524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts", PROFILE_RAW_CONTACTS); 117624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#", 117724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID); 117824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#/data", 117924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID_DATA); 118024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#/entity", 118124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID_ENTITIES); 11825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/status_updates", 11835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROFILE_STATUS_UPDATES); 11843202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contact_entities", 11853202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro PROFILE_RAW_CONTACT_ENTITIES); 118646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 11873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items", STREAM_ITEMS); 11883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/photo", STREAM_ITEMS_PHOTOS); 11893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#", STREAM_ITEMS_ID); 11903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#/photo", STREAM_ITEMS_ID_PHOTOS); 11913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#/photo/#", 11923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann STREAM_ITEMS_ID_PHOTOS_ID); 11933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items_limit", STREAM_ITEMS_LIMIT); 11943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 11955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "display_photo/#", DISPLAY_PHOTO); 1196f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "photo_dimensions", PHOTO_DIMENSIONS); 1197f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 119846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa HashMap<String, Integer> tmpTypeMap = new HashMap<String, Integer>(); 119946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_CALL, DataUsageStatColumns.USAGE_TYPE_INT_CALL); 120046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_LONG_TEXT, 120146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns.USAGE_TYPE_INT_LONG_TEXT); 120246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_SHORT_TEXT, 120346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns.USAGE_TYPE_INT_SHORT_TEXT); 120446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sDataUsageTypeMap = Collections.unmodifiableMap(tmpTypeMap); 120519a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 120619a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 1207d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static class DirectoryInfo { 1208d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String authority; 1209d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountName; 1210d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountType; 1211d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 1212d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 1213d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 1214d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Cached information about contact directories. 1215d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 12164458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private HashMap<String, DirectoryInfo> mDirectoryCache = new HashMap<String, DirectoryInfo>(); 12174458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private boolean mDirectoryCacheValid = false; 1218d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 12193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 122043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * An entry in group id cache. It maps the combination of (account type, account name, data set, 1221ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * and source id) to group row id. 1222ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 1223e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov public static class GroupIdCacheEntry { 1224ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType; 1225ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName; 122643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String dataSet; 1227ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String sourceId; 1228ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov long groupId; 1229ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 1230a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1231e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // We don't need a soft cache for groups - the assumption is that there will only 1232e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // be a small number of contact groups. The cache is keyed off source id. The value 1233e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // is a list of groups with this group id. 1234e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 1235e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov 123624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro /** 1237f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Maximum dimension (height or width) of display photos. Larger images will be scaled 1238f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * to fit. 1239f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 1240f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private int mMaxDisplayPhotoDim; 1241f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1242f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 1243f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Maximum dimension (height or width) of photo thumbnails. 1244f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 1245f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private int mMaxThumbnailPhotoDim; 1246f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 12475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 12485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Sub-provider for handling profile requests against the profile database. 12495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 12505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ProfileProvider mProfileProvider; 1251f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 12524097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1253f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1254315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1255622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1256622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 125772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private ContactDirectoryManager mContactDirectoryManager; 12585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 12605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * The active (thread-local) database. This will be switched between a contacts-specific 12615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * database and a profile-specific database, depending on what the current operation is 12625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * targeted to. 12635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 12645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<SQLiteDatabase> mActiveDb = new ThreadLocal<SQLiteDatabase>(); 12655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // This variable keeps track of whether the current operation is intended for the profile DB. 12675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<Boolean> mInProfileMode = new ThreadLocal<Boolean>(); 12685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Whether we're currently in the process of applying a batch of operations. 12705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<Boolean> mApplyingBatch = new ThreadLocal<Boolean>(); 12715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Separate data row handler instances for contact data and profile data. 12735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private HashMap<String, DataRowHandler> mDataRowHandlers; 12745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private HashMap<String, DataRowHandler> mProfileDataRowHandlers; 12755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Depending on whether the action being performed is for the profile, we will use one of two 12775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // database helper instances. 12785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<ContactsDatabaseHelper> mDbHelper = 12795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ThreadLocal<ContactsDatabaseHelper>(); 12805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ContactsDatabaseHelper mContactsHelper; 12815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ProfileDatabaseHelper mProfileHelper; 12825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Depending on whether the action being performed is for the profile or not, we will use one of 12845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // two aggregator instances. 12855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<ContactAggregator> mAggregator = new ThreadLocal<ContactAggregator>(); 1286622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 12875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ContactAggregator mProfileAggregator; 12885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Depending on whether the action being performed is for the profile or not, we will use one of 12905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // two photo store instances (with their files stored in separate subdirectories). 12915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<PhotoStore> mPhotoStore = new ThreadLocal<PhotoStore>(); 12925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private PhotoStore mContactsPhotoStore; 12935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private PhotoStore mProfilePhotoStore; 12945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // The active transaction context will switch depending on the operation being performed. 12965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Both transaction contexts will be cleared out when a batch transaction is started, and 12975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // each will be processed separately when a batch transaction completes. 12985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private TransactionContext mContactTransactionContext = new TransactionContext(false); 12995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private TransactionContext mProfileTransactionContext = new TransactionContext(true); 13005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<TransactionContext> mTransactionContext = 13015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ThreadLocal<TransactionContext>(); 13025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 13035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // This database reference will only be referenced when a batch operation is in progress 13045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // that includes profile DB operations. It is used to create and handle a separate transaction 13055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // around that batch. Outside of such a batch operation, this will be null. 13065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<SQLiteDatabase> mProfileDbForBatch = 13075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ThreadLocal<SQLiteDatabase>(); 13085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 13095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // This flag is set during a batch operation that involves the profile DB to indicate that 13105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // errors occurred during processing of one of the profile operations. 13115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<Boolean> mProfileErrorsInBatch = new ThreadLocal<Boolean>(); 13125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 1313f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1314a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1315d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov private CommonNicknameCache mCommonNicknameCache; 1316f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private SearchIndexManager mSearchIndexManager; 1317a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 131820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 131973f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov private HashMap<String, Boolean> mAccountWritability = Maps.newHashMap(); 132020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 132109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private int mProviderStatus = ProviderStatus.STATUS_NORMAL; 13223826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private boolean mProviderStatusUpdateNeeded; 132309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private long mEstimatedStorageRequirement = 0; 132415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private volatile CountDownLatch mReadAccessLatch; 132515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private volatile CountDownLatch mWriteAccessLatch; 132615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private boolean mAccountUpdateListenerRegistered; 1327bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private boolean mOkToOpenAccess = true; 132873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 13291a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 13301a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 133181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 133281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 13334cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao private Locale mCurrentLocale; 13343826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private int mContactsAccountCount; 1335d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 1336bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private HandlerThread mBackgroundThread; 1337bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private Handler mBackgroundHandler; 1338bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1339f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private long mLastPhotoCleanup = 0; 1340f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 13414f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 13424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1343663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) { 1344663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki Log.d(Constants.PERFORMANCE_TAG, "ContactsProvider2.onCreate start"); 1345663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } 1346de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 1347ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov try { 1348ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return initialize(); 1349ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } catch (RuntimeException e) { 1350ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov Log.e(TAG, "Cannot start provider", e); 1351ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return false; 1352663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } finally { 1353663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) { 1354663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki Log.d(Constants.PERFORMANCE_TAG, "ContactsProvider2.onCreate finish"); 1355663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } 1356ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 1357ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 135835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1359ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov private boolean initialize() { 136015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov StrictMode.setThreadPolicy( 136115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()); 136215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 13633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Resources resources = getContext().getResources(); 1364f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mMaxDisplayPhotoDim = resources.getInteger( 1365f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro R.integer.config_max_display_photo_dim); 1366f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mMaxThumbnailPhotoDim = resources.getInteger( 1367f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro R.integer.config_max_thumbnail_photo_dim); 13683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 13695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper = (ContactsDatabaseHelper) getDatabaseHelper(); 13705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.set(mContactsHelper); 137172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mContactDirectoryManager = new ContactDirectoryManager(this); 1372a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 137365ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov 1374bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // The provider is closed for business until fully initialized 137515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch = new CountDownLatch(1); 137615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch = new CountDownLatch(1); 137772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 1378bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundThread = new HandlerThread("ContactsProviderWorker", 1379bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov Process.THREAD_PRIORITY_BACKGROUND); 1380bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundThread.start(); 1381bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler = new Handler(mBackgroundThread.getLooper()) { 1382bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 1383bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void handleMessage(Message msg) { 1384bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov performBackgroundTask(msg.what, msg.obj); 1385bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1386bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov }; 13872a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov 13885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Set up the sub-provider for handling profiles. 13895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileProvider = getProfileProvider(); 13905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ProviderInfo profileInfo = new ProviderInfo(); 13915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileInfo.readPermission = "android.permission.READ_PROFILE"; 13925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileInfo.writePermission = "android.permission.WRITE_PROFILE"; 13935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileProvider.attachInfo(getContext(), profileInfo); 13945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper = (ProfileDatabaseHelper) mProfileProvider.getDatabaseHelper(); 13955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 139615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_INITIALIZE); 1397bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS); 1398bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS); 1399bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_LOCALE); 1400bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM); 140105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_SEARCH_INDEX); 1402bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_PROVIDER_STATUS); 140315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_OPEN_WRITE_ACCESS); 1404f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS); 14053826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 140649d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov return true; 14074f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 14084f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1409767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov /** 141051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * (Re)allocates all locale-sensitive structures. 141151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 141204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov private void initForDefaultLocale() { 141315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Context context = getContext(); 14145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mLegacyApiSupport = new LegacyApiSupport(context, mContactsHelper, this, 14155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mGlobalSearchSupport); 14164cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mCurrentLocale = getLocale(); 14175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mNameSplitter = mContactsHelper.createNameSplitter(); 14184cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 14194cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mPostalSplitter = new PostalSplitter(mCurrentLocale); 14205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mCommonNicknameCache = new CommonNicknameCache(mContactsHelper.getReadableDatabase()); 1421cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao ContactLocaleUtils.getIntance().setLocale(mCurrentLocale); 14225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactAggregator = new ContactAggregator(this, mContactsHelper, 142315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov createPhotoPriorityResolver(context), mNameSplitter, mCommonNicknameCache); 14245b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 14255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileAggregator = new ProfileAggregator(this, mProfileHelper, 14265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro createPhotoPriorityResolver(context), mNameSplitter, mCommonNicknameCache); 14275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1428f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSearchIndexManager = new SearchIndexManager(this); 14295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 14305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsPhotoStore = new PhotoStore(getContext().getFilesDir(), mContactsHelper); 14315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfilePhotoStore = new PhotoStore(new File(getContext().getFilesDir(), "profile"), 14325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper); 14335b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 1434bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 14355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro initDataRowHandlers(mDataRowHandlers, mContactsHelper, mContactAggregator, 14365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsPhotoStore); 14375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDataRowHandlers = new HashMap<String, DataRowHandler>(); 14385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro initDataRowHandlers(mProfileDataRowHandlers, mProfileHelper, mProfileAggregator, 14395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfilePhotoStore); 14405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 14415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Set initial thread-local state variables for the Contacts DB. 14425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 14435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 1444bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 14455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private void initDataRowHandlers(Map<String, DataRowHandler> handlerMap, 14465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ContactsDatabaseHelper dbHelper, ContactAggregator contactAggregator, 14475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PhotoStore photoStore) { 14485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Context context = getContext(); 14495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Email.CONTENT_ITEM_TYPE, 14505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForEmail(context, dbHelper, contactAggregator)); 14515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Im.CONTENT_ITEM_TYPE, 14525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForIm(context, dbHelper, contactAggregator)); 14535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Organization.CONTENT_ITEM_TYPE, 14545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForOrganization(context, dbHelper, contactAggregator)); 14555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Phone.CONTENT_ITEM_TYPE, 14565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForPhoneNumber(context, dbHelper, contactAggregator)); 14575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Nickname.CONTENT_ITEM_TYPE, 14585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForNickname(context, dbHelper, contactAggregator)); 14595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(StructuredName.CONTENT_ITEM_TYPE, 14605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForStructuredName(context, dbHelper, contactAggregator, 1461bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mNameSplitter, mNameLookupBuilder)); 14625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(StructuredPostal.CONTENT_ITEM_TYPE, 14635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForStructuredPostal(context, dbHelper, contactAggregator, 1464bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mPostalSplitter)); 14655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(GroupMembership.CONTENT_ITEM_TYPE, 14665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForGroupMembership(context, dbHelper, contactAggregator, 1467bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mGroupIdCache)); 14685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Photo.CONTENT_ITEM_TYPE, 14695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForPhoto(context, dbHelper, contactAggregator, photoStore)); 14705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Note.CONTENT_ITEM_TYPE, 14715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForNote(context, dbHelper, contactAggregator)); 1472bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1473bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1474bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /** 1475bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Visible for testing. 1476bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov */ 1477bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /* package */ PhotoPriorityResolver createPhotoPriorityResolver(Context context) { 1478bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return new PhotoPriorityResolver(context); 1479bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1480bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1481bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void scheduleBackgroundTask(int task) { 1482bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler.sendEmptyMessage(task); 1483bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1484bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1485bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void scheduleBackgroundTask(int task, Object arg) { 1486bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler.sendMessage(mBackgroundHandler.obtainMessage(task, arg)); 1487bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1488bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1489bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void performBackgroundTask(int task, Object arg) { 1490bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov switch (task) { 149115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case BACKGROUND_TASK_INITIALIZE: { 149215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov initForDefaultLocale(); 149315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch.countDown(); 149415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch = null; 149515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov break; 149615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 149715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 149815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case BACKGROUND_TASK_OPEN_WRITE_ACCESS: { 1499bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (mOkToOpenAccess) { 150015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch.countDown(); 150115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch = null; 1502bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1503bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1504bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1505bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1506bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS: { 1507bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1508bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov importLegacyContactsInBackground(); 1509bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1510bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1511bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1512bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1513bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_ACCOUNTS: { 151415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Context context = getContext(); 151515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (!mAccountUpdateListenerRegistered) { 151615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov AccountManager.get(context).addOnAccountsUpdatedListener(this, null, false); 151715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mAccountUpdateListenerRegistered = true; 151815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 151915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 15205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Update the accounts for both the contacts and profile DBs. 152115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Account[] accounts = AccountManager.get(context).getAccounts(); 15225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 1523bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov boolean accountsChanged = updateAccountsInBackground(accounts); 15245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 15255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro accountsChanged |= updateAccountsInBackground(accounts); 15265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 1527bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateContactsAccountCount(accounts); 1528bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateDirectoriesInBackground(accountsChanged); 1529bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1530bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1531bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1532bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_LOCALE: { 1533bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateLocaleInBackground(); 1534bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1535bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1536bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1537fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov case BACKGROUND_TASK_CHANGE_LOCALE: { 1538fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov changeLocaleInBackground(); 1539fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov break; 1540fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1541fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1542bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM: { 1543bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (isAggregationUpgradeNeeded()) { 1544bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov upgradeAggregationAlgorithmInBackground(); 1545bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1546bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1547bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1548bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 154905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_SEARCH_INDEX: { 155005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov updateSearchIndexInBackground(); 155105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov break; 155205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 155305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 1554bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_PROVIDER_STATUS: { 1555bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateProviderStatus(); 1556bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1557bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1558bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1559bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_DIRECTORIES: { 1560bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (arg != null) { 1561bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.onPackageChanged((String) arg); 1562bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1563bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1564bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1565f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1566f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case BACKGROUND_TASK_CLEANUP_PHOTOS: { 1567f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Check rate limit. 1568f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long now = System.currentTimeMillis(); 1569f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (now - mLastPhotoCleanup > PHOTO_CLEANUP_RATE_LIMIT) { 1570f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mLastPhotoCleanup = now; 15715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 15725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Clean up photo stores for both contacts and profiles. 15735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 15745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro cleanupPhotoStore(); 15755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 1576f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro cleanupPhotoStore(); 1577f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro break; 1578f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1579f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1580bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 15814cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 15824cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao 158353fac8f99f3884c372c907a76766d27fa9e1d95fDmitri Plotnikov public void onLocaleChanged() { 15843826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL 15853826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov && mProviderStatus != ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) { 15864f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov return; 15874f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov } 15884f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov 1589fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_CHANGE_LOCALE); 15904cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 159151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 159251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov /** 159351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * Verifies that the contacts database is properly configured for the current locale. 159451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * If not, changes the database locale to the current locale using an asynchronous task. 159551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * This needs to be done asynchronously because the process involves rebuilding 159651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * large data structures (name lookup, sort keys), which can take minutes on 159751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * a large set of contacts. 159851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 1599bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void updateLocaleInBackground() { 1600f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 1601f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // The process is already running - postpone the change 1602f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov if (mProviderStatus == ProviderStatus.STATUS_CHANGING_LOCALE) { 1603f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov return; 1604f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov } 1605f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 160651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 160751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final String providerLocale = prefs.getString(PREF_LOCALE, null); 160851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final Locale currentLocale = mCurrentLocale; 160951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov if (currentLocale.toString().equals(providerLocale)) { 161051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return; 161151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 161251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 161351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov int providerStatus = mProviderStatus; 161451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_CHANGING_LOCALE); 16155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setLocale(this, currentLocale); 16165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper.setLocale(this, currentLocale); 1617bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, currentLocale.toString()).apply(); 1618bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov setProviderStatus(providerStatus); 1619bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 162051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 1621fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov /** 1622fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov * Reinitializes the provider for a new locale. 1623fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov */ 1624fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov private void changeLocaleInBackground() { 1625fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // Re-initializing the provider without stopping it. 1626fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // Locking the database will prevent inserts/updates/deletes from 1627fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // running at the same time, but queries may still be running 1628fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // on other threads. Those queries may return inconsistent results. 16295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mContactsHelper.getWritableDatabase(); 16305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase profileDb = mProfileHelper.getWritableDatabase(); 1631fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.beginTransaction(); 16325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.beginTransaction(); 1633fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov try { 1634fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov initForDefaultLocale(); 1635fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.setTransactionSuccessful(); 16365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.setTransactionSuccessful(); 1637fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } finally { 1638fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.endTransaction(); 16395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.endTransaction(); 1640fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1641fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1642fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov updateLocaleInBackground(); 1643fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1644fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 164505e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov protected void updateSearchIndexInBackground() { 164605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov mSearchIndexManager.updateIndex(); 164705e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 164805e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 1649bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void updateDirectoriesInBackground(boolean rescan) { 1650bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.scanAllPackages(rescan); 165151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 165251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 16533826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private void updateProviderStatus() { 16543826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL 16553826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov && mProviderStatus != ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) { 16563826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return; 16573826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 16583826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 16593e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson // No accounts/no contacts status is true if there are no account and 16605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // there are no contacts or one profile contact 16613e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson if (mContactsAccountCount == 0) { 16625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactsNum = DatabaseUtils.queryNumEntries(mContactsHelper.getReadableDatabase(), 16633e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson Tables.CONTACTS, null); 16645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long profileNum = DatabaseUtils.queryNumEntries(mProfileHelper.getReadableDatabase(), 16655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Tables.CONTACTS, null); 16665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 16675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // TODO: Different status if there is a profile but no contacts? 16685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (contactsNum == 0 && profileNum <= 1) { 16693e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson setProviderStatus(ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS); 16703e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson } else { 16713e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson setProviderStatus(ProviderStatus.STATUS_NORMAL); 16723e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson } 16733826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } else { 16743826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 16753826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 16763826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 16773826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 167831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1679f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro protected void cleanupPhotoStore() { 16805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mDbHelper.get().getWritableDatabase(); 16816802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 16826802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Assemble the set of photo store file IDs that are in use, and send those to the photo 1683f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // store. Any photos that aren't in that set will be deleted, and any photos that no 1684f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // longer exist in the photo store will be returned for us to clear out in the DB. 16857cf50494501938f175d288077145acf49da8f171Daniel Lehmann long photoMimeTypeId = mDbHelper.get().getMimeTypeId(Photo.CONTENT_ITEM_TYPE); 16866802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Cursor c = db.query(Views.DATA, new String[]{Data._ID, Photo.PHOTO_FILE_ID}, 16877cf50494501938f175d288077145acf49da8f171Daniel Lehmann DataColumns.MIMETYPE_ID + "=" + photoMimeTypeId + " AND " 1688f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro + Photo.PHOTO_FILE_ID + " IS NOT NULL", null, null, null, null); 16896802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Set<Long> usedPhotoFileIds = Sets.newHashSet(); 16906802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Map<Long, Long> photoFileIdToDataId = Maps.newHashMap(); 1691f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 1692f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro while (c.moveToNext()) { 16936802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long dataId = c.getLong(0); 16946802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long photoFileId = c.getLong(1); 16956802030a777c0c3ba1dc029c534cca4784260632Dave Santoro usedPhotoFileIds.add(photoFileId); 16966802030a777c0c3ba1dc029c534cca4784260632Dave Santoro photoFileIdToDataId.put(photoFileId, dataId); 16976802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 16986802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } finally { 16996802030a777c0c3ba1dc029c534cca4784260632Dave Santoro c.close(); 17006802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 17016802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 17026802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Also query for all social stream item photos. 1703c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro c = db.query(Tables.STREAM_ITEM_PHOTOS + " JOIN " + Tables.STREAM_ITEMS 1704c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro + " ON " + StreamItemPhotos.STREAM_ITEM_ID + "=" + StreamItemsColumns.CONCRETE_ID 1705c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro + " JOIN " + Tables.RAW_CONTACTS 1706c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro + " ON " + StreamItems.RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID, 17076802030a777c0c3ba1dc029c534cca4784260632Dave Santoro new String[]{ 1708c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro StreamItemPhotosColumns.CONCRETE_ID, 1709c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID, 1710c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro StreamItemPhotos.PHOTO_FILE_ID, 1711c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro RawContacts.ACCOUNT_TYPE, 1712c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro RawContacts.ACCOUNT_NAME 17136802030a777c0c3ba1dc029c534cca4784260632Dave Santoro }, 17146802030a777c0c3ba1dc029c534cca4784260632Dave Santoro null, null, null, null, null); 17156802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Map<Long, Long> photoFileIdToStreamItemPhotoId = Maps.newHashMap(); 17166802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Map<Long, Long> streamItemPhotoIdToStreamItemId = Maps.newHashMap(); 1717c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro Map<Long, Account> streamItemPhotoIdToAccount = Maps.newHashMap(); 17186802030a777c0c3ba1dc029c534cca4784260632Dave Santoro try { 17196802030a777c0c3ba1dc029c534cca4784260632Dave Santoro while (c.moveToNext()) { 17206802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemPhotoId = c.getLong(0); 17216802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemId = c.getLong(1); 17226802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long photoFileId = c.getLong(2); 1723c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro String accountType = c.getString(3); 1724c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro String accountName = c.getString(4); 17256802030a777c0c3ba1dc029c534cca4784260632Dave Santoro usedPhotoFileIds.add(photoFileId); 17266802030a777c0c3ba1dc029c534cca4784260632Dave Santoro photoFileIdToStreamItemPhotoId.put(photoFileId, streamItemPhotoId); 17276802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemPhotoIdToStreamItemId.put(streamItemPhotoId, streamItemId); 1728c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro Account account = new Account(accountName, accountType); 1729c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro streamItemPhotoIdToAccount.put(photoFileId, account); 1730f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1731f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 1732f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 1733f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1734f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1735f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Run the photo store cleanup. 17365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> missingPhotoIds = mPhotoStore.get().cleanup(usedPhotoFileIds); 1737f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1738f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // If any of the keys we're using no longer exist, clean them up. 17396802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (!missingPhotoIds.isEmpty()) { 1740f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ArrayList<ContentProviderOperation> ops = Lists.newArrayList(); 17416802030a777c0c3ba1dc029c534cca4784260632Dave Santoro for (long missingPhotoId : missingPhotoIds) { 17426802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoFileIdToDataId.containsKey(missingPhotoId)) { 17436802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long dataId = photoFileIdToDataId.get(missingPhotoId); 1744f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ContentValues updateValues = new ContentValues(); 1745f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.putNull(Photo.PHOTO_FILE_ID); 1746f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ops.add(ContentProviderOperation.newUpdate( 17476802030a777c0c3ba1dc029c534cca4784260632Dave Santoro ContentUris.withAppendedId(Data.CONTENT_URI, dataId)) 1748f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .withValues(updateValues).build()); 1749f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 17506802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoFileIdToStreamItemPhotoId.containsKey(missingPhotoId)) { 17516802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // For missing photos that were in stream item photos, just delete the stream 17526802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // item photo. 17536802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemPhotoId = photoFileIdToStreamItemPhotoId.get(missingPhotoId); 17546802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemId = streamItemPhotoIdToStreamItemId.get(streamItemPhotoId); 1755c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro Account account = streamItemPhotoIdToAccount.get(missingPhotoId); 17566802030a777c0c3ba1dc029c534cca4784260632Dave Santoro ops.add(ContentProviderOperation.newDelete( 17576802030a777c0c3ba1dc029c534cca4784260632Dave Santoro StreamItems.CONTENT_URI.buildUpon() 17586802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .appendPath(String.valueOf(streamItemId)) 17596802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .appendPath(StreamItems.StreamItemPhotos.CONTENT_DIRECTORY) 17606802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .appendPath(String.valueOf(streamItemPhotoId)) 1761c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro .appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name) 1762c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro .appendQueryParameter(RawContacts.ACCOUNT_TYPE, account.type) 17636802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .build()).build()); 17646802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 1765f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1766f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 1767f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro applyBatch(ops); 1768f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } catch (OperationApplicationException oae) { 1769f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Not a fatal problem (and we'll try again on the next cleanup). 1770f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Log.e(TAG, "Failed to clean up outdated photo references", oae); 1771f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1772f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1773f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1774f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1775f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /* Visible for testing */ 1776de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 1777b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 1778b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 177931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 178031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 17815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public ProfileProvider getProfileProvider() { 17825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return new ProfileProvider(this); 17835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 17845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 1785524913c66ce75ca8dec127ac88e3bc2249c246d9Dave Santoro @VisibleForTesting 1786f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /* package */ PhotoStore getPhotoStore() { 17875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mContactsPhotoStore; 1788f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1789f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 179087614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro /* package */ int getMaxDisplayPhotoDim() { 179187614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro return mMaxDisplayPhotoDim; 179287614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro } 179387614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro 179487614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro /* package */ int getMaxThumbnailPhotoDim() { 179587614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro return mMaxThumbnailPhotoDim; 179687614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro } 179787614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro 1798013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1799013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1800013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1801013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 18025df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov /* package */ NameLookupBuilder getNameLookupBuilder() { 18035df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov return mNameLookupBuilder; 18045df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov } 18055df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov 18065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov /* Visible for testing */ 1807ed78fd6df5e9f3a2d572162e5d374d1f4a625bddDmitri Plotnikov public ContactDirectoryManager getContactDirectoryManagerForTest() { 180872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov return mContactDirectoryManager; 180972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 181072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 181172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /* Visible for testing */ 18125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov protected Locale getLocale() { 18135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov return Locale.getDefault(); 18145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 18155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 18165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean applyingBatch() { 18175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Boolean applyingBatch = mApplyingBatch.get(); 18185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return applyingBatch != null && applyingBatch; 18195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 18205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 18215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean inProfileMode() { 18225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Boolean profileMode = mInProfileMode.get(); 18235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return profileMode != null && profileMode; 18245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 18255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 18263d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 18275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int version = Integer.parseInt( 18285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.getProperty(PROPERTY_CONTACTS_IMPORTED, "0")); 1829b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return version < PROPERTY_CONTACTS_IMPORT_VERSION; 18303d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18313d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1832568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1833568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1834568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1835568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1836568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1837bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Imports legacy contacts as a background task. 1838568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1839bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private void importLegacyContactsInBackground() { 1840bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Importing legacy contacts"); 1841bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADING); 1842568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1843bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 18445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setLocale(this, mCurrentLocale); 1845bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, mCurrentLocale.toString()).commit(); 1846568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1847bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1848bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (importLegacyContacts(importer)) { 1849bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov onLegacyContactImportSuccess(); 1850bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } else { 1851bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov onLegacyContactImportFailure(); 1852bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1853568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1854568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1855bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1856bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Unlocks the provider and declares that the import process is complete. 1857bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1858bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportSuccess() { 1859bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 1860bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)getContext().getSystemService(Context.NOTIFICATION_SERVICE); 1861bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.cancel(LEGACY_IMPORT_FAILED_NOTIFICATION); 1862bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1863b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov // Store a property in the database indicating that the conversion process succeeded 18645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setProperty(PROPERTY_CONTACTS_IMPORTED, 1865b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov String.valueOf(PROPERTY_CONTACTS_IMPORT_VERSION)); 1866bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 1867bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Completed import of legacy contacts"); 1868bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1869bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1870bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1871bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Announces the provider status and keeps the provider locked. 1872bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1873bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportFailure() { 1874bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Context context = getContext(); 1875bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 1876bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); 1877bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1878bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // Show a notification 1879bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Notification n = new Notification(android.R.drawable.stat_notify_error, 1880bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_ticker), 1881bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov System.currentTimeMillis()); 1882bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.setLatestEventInfo(context, 1883bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_title), 1884bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_text), 1885bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov PendingIntent.getActivity(context, 0, new Intent(Intents.UI.LIST_DEFAULT), 0)); 1886bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; 1887bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1888bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.notify(LEGACY_IMPORT_FAILED_NOTIFICATION, n); 1889bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1890bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADE_OUT_OF_MEMORY); 1891bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Failed to import legacy contacts"); 1892bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1893bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // Do not let any database changes until this issue is resolved. 1894bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mOkToOpenAccess = false; 18953d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18963d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 18973d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1898568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 18990e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 19003d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 19013d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 1902bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (importer.importContacts()) { 1903bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1904bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // TODO aggregate all newly added raw contacts 1905bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mContactAggregator.setEnabled(aggregatorEnabled); 1906bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return true; 1907bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 19083d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 19093d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 19103d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1911bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mEstimatedStorageRequirement = importer.getEstimatedStorageRequirement(); 1912bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return false; 19133d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 19143d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1915a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1916a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1917a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1918a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 19195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.wipeData(); 19205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper.wipeData(); 19215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsPhotoStore.clear(); 19225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfilePhotoStore.clear(); 19233826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatus = ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS; 1924a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1925a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1926568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 192715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov * During intialization, this content provider will 1928568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1929568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1930568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1931568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1932568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 193315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private void waitForAccess(CountDownLatch latch) { 193415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (latch == null) { 193515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return; 193615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 193715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 193815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov while (true) { 193915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov try { 194015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov latch.await(); 194115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return; 194215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } catch (InterruptedException e) { 194315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Thread.currentThread().interrupt(); 1944ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1945568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1946568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1947568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 19485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 19495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Determines whether the given URI should be directed to the profile 19505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * database rather than the contacts database. This is true under either 19515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * of three conditions: 19525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * 1. The URI itself is specifically for the profile. 19535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * 2. The URI contains ID references that are in the profile ID-space. 19545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * 3. The URI contains lookup key references that match the special profile lookup key. 19555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param uri The URI to examine. 19565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @return Whether to direct the DB operation to the profile database. 19575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 19585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean mapsToProfileDb(Uri uri) { 19595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return sUriMatcher.mapsToProfile(uri); 19605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 19625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 19635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Determines whether the given URI with the given values being inserted 19645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * should be directed to the profile database rather than the contacts 19655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * database. This is true if the URI already maps to the profile DB from 19665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * a call to {@link #mapsToProfileDb} or if the URI matches a URI that 19675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * specifies parent IDs via the ContentValues, and the given ContentValues 19685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * contains an ID in the profile ID-space. 19695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param uri The URI to examine. 19705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param values The values being inserted. 19715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @return Whether to direct the DB insert to the profile database. 19725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 19735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean mapsToProfileDbWithInsertedValues(Uri uri, ContentValues values) { 19745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 19755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return true; 19765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int match = sUriMatcher.match(uri); 19785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (INSERT_URI_ID_VALUE_MAP.containsKey(match)) { 19795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String idField = INSERT_URI_ID_VALUE_MAP.get(match); 19805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (values.containsKey(idField)) { 19815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long id = values.getAsLong(idField); 19825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (ContactsContract.isProfileId(id)) { 19835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return true; 19845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return false; 19885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 19905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 19915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Switches the provider's thread-local context variables to prepare for performing 19925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * a profile operation. 19935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 19945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private void switchToProfileMode() { 19955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.set(mProfileHelper); 19965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.set(mProfileTransactionContext); 19975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.set(mProfileAggregator); 19985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mPhotoStore.set(mProfilePhotoStore); 19995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mInProfileMode.set(true); 20005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 20015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // If we're in batch mode and don't yet have a database set up for our transaction, 20025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // get one and start a transaction now. 20035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (applyingBatch() && mProfileDbForBatch.get() == null) { 20045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase profileDb = mProfileHelper.getWritableDatabase(); 20055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.beginTransactionWithListener(this); 20065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDbForBatch.set(profileDb); 20075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 20105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 20115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Switches the provider's thread-local context variables to prepare for performing 20125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * a contacts operation. 20135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 20145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private void switchToContactMode() { 20155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.set(mContactsHelper); 20165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.set(mContactTransactionContext); 20175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.set(mContactAggregator); 20185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mPhotoStore.set(mContactsPhotoStore); 20195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mInProfileMode.set(false); 20205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 20215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // If not in batch mode, clear out the active database - it will be set to the default 20225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // instance from SQLiteContentProvider if necessary. 20235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (!applyingBatch()) { 20245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(null); 20255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 2028568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2029568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 203015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 20315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDbWithInsertedValues(uri, values)) { 2032072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro if (applyingBatch()) { 2033072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2034072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return mProfileProvider.insert(uri, values); 2035072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } else { 2036072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Start a contacts DB transaction to maintain provider synchronization. 2037072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro SQLiteDatabase contactsDb = mContactsHelper.getWritableDatabase(); 2038072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.beginTransactionWithListener(this); 2039072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro Uri result = null; 2040072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro try { 2041072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Now switch to profile mode and proceed with the insert using its provider. 2042072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2043072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro result = mProfileProvider.insert(uri, values); 2044072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2045072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.setTransactionSuccessful(); 2046072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } finally { 2047072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Finish the contacts transaction, allowing other provider operations to 2048072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // proceed. 2049072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.endTransaction(); 2050072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 2051072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return result; 2052072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 20535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 20545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 20555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return super.insert(uri, values); 20565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 2057568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2058568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2059568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2060568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 206115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (mWriteAccessLatch != null) { 2062bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // We are stuck trying to upgrade contacts db. The only update request 2063bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // allowed in this case is an update of provider status, which will trigger 2064bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // an attempt to upgrade contacts again. 2065bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov int match = sUriMatcher.match(uri); 2066bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (match == PROVIDER_STATUS) { 2067bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Integer newStatus = values.getAsInteger(ProviderStatus.STATUS); 2068bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (newStatus != null && newStatus == ProviderStatus.STATUS_UPGRADING) { 2069bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS); 2070bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 1; 2071bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 2072bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 0; 2073bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2074bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2075bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 207615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 20775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 2078072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro if (applyingBatch()) { 2079072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2080072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return mProfileProvider.update(uri, values, selection, selectionArgs); 2081072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } else { 2082072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Start a contacts DB transaction to maintain provider synchronization. 2083072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro SQLiteDatabase contactsDb = mContactsHelper.getWritableDatabase(); 2084072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.beginTransactionWithListener(this); 2085072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro int result = 0; 2086072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro try { 2087072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Now switch to profile mode and proceed with the update using its provider. 2088072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2089072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro result = mProfileProvider.update(uri, values, selection, selectionArgs); 2090072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2091072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.setTransactionSuccessful(); 2092072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } finally { 2093072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Finish the contacts transaction, allowing other provider operations to 2094072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // proceed. 2095072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.endTransaction(); 2096072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 2097072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return result; 2098072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 20995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 21005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 21015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return super.update(uri, values, selection, selectionArgs); 21025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 2103568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2104568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2105568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2106568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 210715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 21085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 2109072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro if (applyingBatch()) { 2110072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2111072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return mProfileProvider.delete(uri, selection, selectionArgs); 2112072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } else { 2113072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Start a contacts DB transaction to maintain provider synchronization. 2114072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro SQLiteDatabase contactsDb = mContactsHelper.getWritableDatabase(); 2115072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.beginTransactionWithListener(this); 2116072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro int result = 0; 2117072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro try { 2118072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Now switch to profile mode and proceed with the delete using its provider. 2119072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2120072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro result = mProfileProvider.delete(uri, selection, selectionArgs); 2121072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2122072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.setTransactionSuccessful(); 2123072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } finally { 2124072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Finish the contacts transaction, allowing other provider operations to 2125072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // proceed. 2126072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.endTransaction(); 2127072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 2128072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return result; 2129072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 21305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 21315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 21325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return super.delete(uri, selection, selectionArgs); 21335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 21365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 21375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Replaces the current (thread-local) database to use for the operation with the given one. 21385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param db The database to use. 21395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 21405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /* package */ void substituteDb(SQLiteDatabase db) { 21415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(db); 2142568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2143568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2144568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2145568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 2146568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 214715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 21485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ContentProviderResult[] results = null; 21495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro try { 2150d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro mApplyingBatch.set(true); 21515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro results = super.applyBatch(operations); 21525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } finally { 2153d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro mApplyingBatch.set(false); 21545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mProfileDbForBatch.get() != null) { 21555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // A profile operation was involved, so clean up its transaction. 21565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro boolean profileErrors = mProfileErrorsInBatch.get() != null 21575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro && mProfileErrorsInBatch.get(); 21585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (!profileErrors) { 21595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDbForBatch.get().setTransactionSuccessful(); 21605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDbForBatch.get().endTransaction(); 21625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDbForBatch.set(null); 21635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileErrorsInBatch.set(false); 21645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return results; 2167568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2168568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 21694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 21707b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov public int bulkInsert(Uri uri, ContentValues[] values) { 21717b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov waitForAccess(mWriteAccessLatch); 2172720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro 2173720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro // Note: This duplicates much of the logic in the superclass, but handles toggling 2174720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro // into profile mode if necessary. 2175720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro int numValues = values.length; 2176720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro boolean notifyChange = false; 2177720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro SQLiteDatabase profileDb = null; 2178072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2179072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Always get a contacts DB and start a transaction on it, to maintain provider 2180072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // synchronization. 21818d55bbc171bea632e960e0e5a88557cef5e66d92Dave Santoro mDb = mContactsHelper.getWritableDatabase(); 21828d55bbc171bea632e960e0e5a88557cef5e66d92Dave Santoro mDb.beginTransactionWithListener(this); 2183720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro try { 2184720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro for (int i = 0; i < numValues; i++) { 2185720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro Uri result; 2186720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (mapsToProfileDbWithInsertedValues(uri, values[i])) { 2187720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro switchToProfileMode(); 2188072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2189072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Initialize the profile DB and start a profile transaction if we haven't 2190072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // already done so. 2191720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (profileDb == null) { 2192720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro profileDb = mProfileHelper.getWritableDatabase(); 2193720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro profileDb.beginTransactionWithListener(this); 2194720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2195720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro result = mProfileProvider.insertInTransaction(uri, values[i]); 2196720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } else { 2197720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro switchToContactMode(); 2198720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro result = insertInTransaction(uri, values[i]); 2199720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2200720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (result != null) { 2201720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro notifyChange = true; 2202720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2203720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro boolean savedNotifyChange = notifyChange; 2204720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro mActiveDb.get().yieldIfContendedSafely(); 2205720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro notifyChange = savedNotifyChange; 2206720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 22078d55bbc171bea632e960e0e5a88557cef5e66d92Dave Santoro mDb.setTransactionSuccessful(); 2208720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (profileDb != null) { 2209720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro profileDb.setTransactionSuccessful(); 2210720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2211720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } finally { 22128d55bbc171bea632e960e0e5a88557cef5e66d92Dave Santoro mDb.endTransaction(); 2213720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (profileDb != null) { 2214720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro profileDb.endTransaction(); 2215720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2216720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2217720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro 2218720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (notifyChange) { 2219720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro notifyChange(); 2220720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2221720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro return numValues; 22227b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov } 22237b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov 22247b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov @Override 2225285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 2226bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2227b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 2228b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2229285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 22305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (inProfileMode()) { 22315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileAggregator.clearPendingAggregations(); 22325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileTransactionContext.clear(); 22335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 22345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactAggregator.clearPendingAggregations(); 22355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactTransactionContext.clear(); 22365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 2237b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2238b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2239285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2240285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2241285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 22421129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 2243bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2244b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 2245b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2246285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 2247b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 22485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().aggregateInTransaction(mTransactionContext.get(), mActiveDb.get()); 22491a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 22501a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 22515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().updateAllVisible(); 22521a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 22533826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 2254bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 2255bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov 22563826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatusUpdateNeeded) { 22573826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateProviderStatus(); 22583826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = false; 22593826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 2260b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2261b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2262bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov private void updateSearchIndexInTransaction() { 22635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> staleContacts = mTransactionContext.get().getStaleSearchIndexContactIds(); 22645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> staleRawContacts = mTransactionContext.get().getStaleSearchIndexRawContactIds(); 2265bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov if (!staleContacts.isEmpty() || !staleRawContacts.isEmpty()) { 2266bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov mSearchIndexManager.updateIndexForRawContacts(staleContacts, staleRawContacts); 22675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().clearSearchIndexUpdates(); 2268bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov } 2269bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov } 2270bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov 2271b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 2272bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2273b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 2274b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 22751129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 22765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro for (long rawContactId : mTransactionContext.get().getInsertedRawContactIds()) { 22775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().updateRawContactDisplayName(mActiveDb.get(), rawContactId); 22785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().onRawContactInsert(mTransactionContext.get(), mActiveDb.get(), 22795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro rawContactId); 228024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 228124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 22825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> dirtyRawContacts = mTransactionContext.get().getDirtyRawContactIds(); 2283d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (!dirtyRawContacts.isEmpty()) { 2284a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2285a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 2286d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov appendIds(mSb, dirtyRawContacts); 2287a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 22885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(mSb.toString()); 2289a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 2290a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 22915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> updatedRawContacts = mTransactionContext.get().getUpdatedRawContactIds(); 2292d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (!updatedRawContacts.isEmpty()) { 2293a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2294a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 2295d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov appendIds(mSb, updatedRawContacts); 2296a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 22975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(mSb.toString()); 2298b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2299b5a4add17815167d20a90645779df34cdf45280dFred Quintana 23005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Update sync states. 23015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro for (Map.Entry<Long, Object> entry : mTransactionContext.get().getUpdatedSyncStates()) { 2302b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 23035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().getSyncState().update(mActiveDb.get(), id, entry.getValue()) <= 0) { 23049d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana throw new IllegalStateException( 23059d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana "unable to update sync state, does it still exist?"); 23069d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana } 2307b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2308b5a4add17815167d20a90645779df34cdf45280dFred Quintana 23095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().clear(); 2310b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2311b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2312a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** 2313a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * Appends comma separated ids. 2314a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * @param ids Should not be empty 2315a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov */ 2316d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov private void appendIds(StringBuilder sb, Set<Long> ids) { 2317b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 2318a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(id).append(','); 2319b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2320a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2321a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 2322285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2323285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2324285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2325cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 232681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 232781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 232881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 232981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 233081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 233181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 233281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 2333cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 2334568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 233551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void setProviderStatus(int status) { 23363826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != status) { 23373826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatus = status; 23383826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov getContext().getContentResolver().notifyChange(ProviderStatus.CONTENT_URI, null, false); 23393826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 234051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 234151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 2342f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public DataRowHandler getDataRowHandler(final String mimeType) { 23435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (inProfileMode()) { 23445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return getDataRowHandlerForProfile(mimeType); 23455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 23473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 23486d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov handler = new DataRowHandlerForCustomMimetype( 23495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro getContext(), mContactsHelper, mContactAggregator, mimeType); 23503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 23513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 23523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 23533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 23543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 23555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public DataRowHandler getDataRowHandlerForProfile(final String mimeType) { 23565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro DataRowHandler handler = mProfileDataRowHandlers.get(mimeType); 23575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (handler == null) { 23585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handler = new DataRowHandlerForCustomMimetype( 23595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro getContext(), mProfileHelper, mProfileAggregator, mimeType); 23605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDataRowHandlers.put(mimeType, handler); 23615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return handler; 23635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 23654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2366de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 2367bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 23681129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Log.v(TAG, "insertInTransaction: " + uri + " " + values); 2369b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2370f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 23715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 23725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 23735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 23745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 2376f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2377f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2378f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2379a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 2380a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 238135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2382a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 238335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 23845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 23855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = mDbHelper.get().getSyncState().insert(mActiveDb.get(), values); 238635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 238735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2388d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2389d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 23906bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 23916bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 23926bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 239324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: { 239424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro throw new UnsupportedOperationException( 239524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro "The profile contact is created automatically"); 239624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 239724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 2398d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS: 2399d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS: { 24005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = insertRawContact(uri, values, callerIsSyncAdapter); 2401f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2402a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2403a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2404a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2405d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_DATA: 2406d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID_DATA: { 2407d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro int segment = match == RAW_CONTACTS_DATA ? 1 : 2; 2408d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(segment)); 2409f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2410f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2411a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2412a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2413a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 24143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case RAW_CONTACTS_ID_STREAM_ITEMS: { 24153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.put(StreamItems.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 24163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItem(uri, values); 24173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 24210c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case DATA: 24220c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case PROFILE_DATA: { 2423f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2424f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2425a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2426a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2427a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2428ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2429f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertGroup(uri, values, callerIsSyncAdapter); 2430f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2431ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2432ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2433ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2434eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 24355aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 243643880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2437eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2438eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2439eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 24405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 24415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 244282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 24431f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 24441f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 24451f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 24463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 24473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItem(uri, values); 24483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 24523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 24533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItemPhoto(uri, values); 24543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 24583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 24593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.put(StreamItemPhotos.STREAM_ITEM_ID, uri.getPathSegments().get(1)); 24603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItemPhoto(uri, values); 24613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 2465a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 246681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2467f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 2468a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2469a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 24707e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 24717e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 24727e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 24737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2474de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 2475a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2476a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2477a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2478e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * If account is non-null then store it in the values. If the account is 2479e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * already specified in the values then it must be consistent with the 2480e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * account, if it is non-null. 2481e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * 2482e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param uri Current {@link Uri} being operated on. 2483e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param values {@link ContentValues} to read and possibly update. 2484e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when only one of 2485e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_NAME} or 2486e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_TYPE} is specified, leaving the 2487e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * other undefined. 2488e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when {@link RawContacts#ACCOUNT_NAME} 2489e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * and {@link RawContacts#ACCOUNT_TYPE} are inconsistent between 2490e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * the given {@link Uri} and {@link ContentValues}. 24917e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 2492e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey private Account resolveAccount(Uri uri, ContentValues values) throws IllegalArgumentException { 2493f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 2494f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 2495e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 2496f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2497f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 2498f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2499e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialValues = TextUtils.isEmpty(valueAccountName) 2500e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ^ TextUtils.isEmpty(valueAccountType); 2501e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2502e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri || partialValues) { 2503e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 25045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 2505fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 2506e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2507e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2508e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 2509e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 2510e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validUri = !TextUtils.isEmpty(accountName); 2511e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validValues = !TextUtils.isEmpty(valueAccountName); 2512e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2513e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validValues && validUri) { 2514e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Check that accounts match when both present 2515e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean accountMatch = TextUtils.equals(accountName, valueAccountName) 2516e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey && TextUtils.equals(accountType, valueAccountType); 2517e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (!accountMatch) { 25185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 2519fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "When both specified, ACCOUNT_NAME and ACCOUNT_TYPE must match", uri)); 2520e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2521e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validUri) { 2522e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Fill values from Uri when not present 2523f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, accountName); 2524f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, accountType); 2525e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validValues) { 2526f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountName = valueAccountName; 2527f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountType = valueAccountType; 2528e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else { 2529e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return null; 2530f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2531f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2532e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Use cached Account object when matches, otherwise create 2533f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mAccount == null 2534f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.name.equals(accountName) 2535f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.type.equals(accountType)) { 2536f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mAccount = new Account(accountName, accountType); 2537035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2538f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2539e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return mAccount; 25407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 254343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * Resolves the account and builds an {@link AccountWithDataSet} based on the data set specified 254443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * in the URI or values (if any). 254543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * @param uri Current {@link Uri} being operated on. 254643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * @param values {@link ContentValues} to read and possibly update. 254743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro */ 254843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro private AccountWithDataSet resolveAccountWithDataSet(Uri uri, ContentValues values) { 25493593682b8d9213fde576a0cff54458ad50563980Dave Santoro final Account account = resolveAccount(uri, values); 255043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro AccountWithDataSet accountWithDataSet = null; 255143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (account != null) { 255243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String dataSet = getQueryParameter(uri, RawContacts.DATA_SET); 255343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (dataSet == null) { 25543593682b8d9213fde576a0cff54458ad50563980Dave Santoro dataSet = values.getAsString(RawContacts.DATA_SET); 2555a71dc460ca951c7aca591f3f470c160cde70a1e3Dave Santoro } else { 25563593682b8d9213fde576a0cff54458ad50563980Dave Santoro values.put(RawContacts.DATA_SET, dataSet); 255743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 255843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet = new AccountWithDataSet(account.name, account.type, dataSet); 255943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 256043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro return accountWithDataSet; 256143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 256243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 256343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro /** 2564d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 25656bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 25666bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 25676bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 25686bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2569d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2570de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 25716bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 25726bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 25736bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 257424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * Inserts an item in the raw contacts table 2575a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2576f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param uri the values for the new row 2577f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param values the account this contact should be associated with. may be null. 2578dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana * @param callerIsSyncAdapter 2579a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2580a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 25815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private long insertRawContact(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 2582f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2583f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2584f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2585f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 258643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro AccountWithDataSet accountWithDataSet = resolveAccountWithDataSet(uri, mValues); 25877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25883d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 25893d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 2590f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 25913d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 25923d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 25935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long rawContactId = mActiveDb.get().insert(Tables.RAW_CONTACTS, 25945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro RawContacts.CONTACT_ID, mValues); 2595f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = RawContacts.AGGREGATION_MODE_DEFAULT; 25965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mValues.containsKey(RawContacts.AGGREGATION_MODE)) { 2597f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov aggregationMode = mValues.getAsInteger(RawContacts.AGGREGATION_MODE); 2598f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 25995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markNewForAggregation(rawContactId, aggregationMode); 2600285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 26015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Trigger creation of a Contact based on this RawContact at the end of transaction 26025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().rawContactInserted(rawContactId, accountWithDataSet); 2603f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2604dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 2605dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 2606dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long starred = values.getAsLong(RawContacts.STARRED); 2607dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (starred != null && starred != 0) { 2608dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred != 0); 2609dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2610dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2611dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 26123826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 2613023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2614a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2615a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2616dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void addAutoAddMembership(long rawContactId) { 2617dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID, 2618dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 2619dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 2620dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 2621dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2622dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2623dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2624dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private Long findGroupByRawContactId(String selection, long rawContactId) { 26255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.GROUPS + "," + Tables.RAW_CONTACTS, 26265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROJECTION_GROUP_ID, selection, 2627dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}, 2628dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana null /* groupBy */, null /* having */, null /* orderBy */); 2629dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 2630dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (c.moveToNext()) { 2631dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return c.getLong(0); 2632dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2633dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return null; 2634dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 2635dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana c.close(); 2636dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2637dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2638dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2639dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void updateFavoritesMembership(long rawContactId, boolean isStarred) { 2640dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID, 2641dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 2642dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 2643dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (isStarred) { 2644dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 2645dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 2646dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana deleteDataGroupMembership(rawContactId, groupId); 2647dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2648dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2649dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2650dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2651dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void insertDataGroupMembership(long rawContactId, long groupId) { 2652dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ContentValues groupMembershipValues = new ContentValues(); 2653dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.GROUP_ROW_ID, groupId); 2654dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.RAW_CONTACT_ID, rawContactId); 2655dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(DataColumns.MIMETYPE_ID, 26565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 26575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().insert(Tables.DATA, null, groupMembershipValues); 2658dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2659dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2660dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void deleteDataGroupMembership(long rawContactId, long groupId) { 2661dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final String[] selectionArgs = { 26625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Long.toString(mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)), 2663dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(groupId), 2664dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(rawContactId)}; 26655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.DATA, SELECTION_GROUPMEMBERSHIP_DATA, selectionArgs); 2666dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2667dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2668a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2669a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2670a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2671a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2672a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2673a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2674f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2675a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2676de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2677de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 267867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2679de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 268020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2681de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2682de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2683de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 26845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(DataColumns.PACKAGE_ID, mDbHelper.get().getPackageId(packageName)); 2685de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2686de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2687508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2688de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2689de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2690de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2691de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2692de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 26934097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 26945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.get().getMimeTypeId(mimeType)); 2695de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2696a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2697a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 26985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = rowHandler.insert(mActiveDb.get(), mTransactionContext.get(), rawContactId, mValues); 2699f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 27005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().markRawContactDirty(rawContactId); 2701a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 27025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().rawContactUpdated(rawContactId); 2703a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 27044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 27054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 27063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 27073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Inserts an item in the stream_items table. The account is checked against the 27083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account in the raw contact for which the stream item is being inserted. If the 27093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * new stream item results in more stream items under this raw contact than the limit, 27103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the oldest one will be deleted (note that if the stream item inserted was the 27113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * oldest, it will be immediately deleted, and this will return 0). 27123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 27133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param uri the insertion URI 27143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param values the values for the new row 27153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return the stream item _ID of the newly created row, or 0 if it was not created 27163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 27173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long insertStreamItem(Uri uri, ContentValues values) { 27183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long id = 0; 27193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.clear(); 27203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.putAll(values); 27213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = mValues.getAsLong(StreamItems.RAW_CONTACT_ID); 27233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Ensure that the raw contact exists and belongs to the caller's account. 27253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, mValues); 27263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, rawContactId); 27273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27286802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to insert accounts params - they don't exist in the stream items table. 27296802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_NAME); 27306802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_TYPE); 27316802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 27323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Insert the new stream item. 27335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = mActiveDb.get().insert(Tables.STREAM_ITEMS, null, mValues); 27346802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (id == -1) { 27356802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Insertion failed. 27366802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return 0; 27376802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 27383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check to see if we're over the limit for stream items under this raw contact. 27403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // It's possible that the inserted stream item is older than the the existing 27413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // ones, in which case it may be deleted immediately (resetting the ID to 0). 27423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = cleanUpOldStreamItems(rawContactId, id); 27433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return id; 27453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 27463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 27483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Inserts an item in the stream_item_photos table. The account is checked against 27493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the account in the raw contact that owns the stream item being modified. 27503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 27513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param uri the insertion URI 27523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param values the values for the new row 27536802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @return the stream item photo _ID of the newly created row, or 0 if there was an issue 27546802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * with processing the photo or creating the row 27553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 27563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long insertStreamItemPhoto(Uri uri, ContentValues values) { 27573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long id = 0; 27583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.clear(); 27593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.putAll(values); 27603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long streamItemId = mValues.getAsLong(StreamItemPhotos.STREAM_ITEM_ID); 27623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (streamItemId != 0) { 27633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = lookupRawContactIdForStreamId(streamItemId); 27643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Ensure that the raw contact exists and belongs to the caller's account. 27663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, mValues); 27673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, rawContactId); 27683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27696802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to insert accounts params - they don't exist in the stream item 27706802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // photos table. 27716802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_NAME); 27726802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_TYPE); 27733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27746802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Process the photo and store it. 27756802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (processStreamItemPhoto(mValues, false)) { 27766802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Insert the stream item photo. 27775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = mActiveDb.get().insert(Tables.STREAM_ITEM_PHOTOS, null, mValues); 27786802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 27793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 27803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return id; 27813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 27823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 27846802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * Processes the photo contained in the {@link ContactsContract.StreamItemPhotos#PHOTO} 27856802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * field of the given values, attempting to store it in the photo store. If successful, 27866802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * the resulting photo file ID will be added to the values for insert/update in the table. 27876802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * <p> 27886802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * If updating, it is valid for the picture to be empty or unspecified (the function will 27896802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * still return true). If inserting, a valid picture must be specified. 27906802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @param values The content values provided by the caller. 27916802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @param forUpdate Whether this photo is being processed for update (vs. insert). 27926802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @return Whether the insert or update should proceed. 27936802030a777c0c3ba1dc029c534cca4784260632Dave Santoro */ 27946802030a777c0c3ba1dc029c534cca4784260632Dave Santoro private boolean processStreamItemPhoto(ContentValues values, boolean forUpdate) { 27956802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (!values.containsKey(StreamItemPhotos.PHOTO)) { 27966802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return forUpdate; 27976802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 27986802030a777c0c3ba1dc029c534cca4784260632Dave Santoro byte[] photoBytes = values.getAsByteArray(StreamItemPhotos.PHOTO); 27996802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoBytes == null) { 28006802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return forUpdate; 28016802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28026802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 28036802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Process the photo and store it. 28046802030a777c0c3ba1dc029c534cca4784260632Dave Santoro try { 28055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long photoFileId = mPhotoStore.get().insert(new PhotoProcessor(photoBytes, 28061dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro mMaxDisplayPhotoDim, mMaxThumbnailPhotoDim, true), true); 28076802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoFileId != 0) { 28086802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.put(StreamItemPhotos.PHOTO_FILE_ID, photoFileId); 28096802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(StreamItemPhotos.PHOTO); 28106802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return true; 28116802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } else { 28126802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Couldn't store the photo, return 0. 28136802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Log.e(TAG, "Could not process stream item photo for insert"); 28146802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return false; 28156802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28166802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } catch (IOException ioe) { 28176802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Log.e(TAG, "Could not process stream item photo for insert", ioe); 28186802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return false; 28196802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28206802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28216802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 28226802030a777c0c3ba1dc029c534cca4784260632Dave Santoro /** 28233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Looks up the raw contact ID that owns the specified stream item. 28243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param streamItemId The ID of the stream item. 28253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The associated raw contact ID, or -1 if no such stream item exists. 28263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 28273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long lookupRawContactIdForStreamId(long streamItemId) { 28283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = -1; 28295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, 28305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{StreamItems.RAW_CONTACT_ID}, 28313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItems._ID + "=?", new String[]{String.valueOf(streamItemId)}, 28323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 28333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 28343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (c.moveToFirst()) { 28353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann rawContactId = c.getLong(0); 28363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 28383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 28393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return rawContactId; 28413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 28433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 28443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given raw contact ID is owned by the given account. 28453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * If the resolved account is null, this will return true iff the raw contact 28463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * is also associated with the "null" account. 28473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 28483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * If the resolved account does not match, this will throw a security exception. 28493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 28503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param rawContactId The raw contact ID to check for. 28513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 28523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void enforceModifyingAccount(Account account, long rawContactId) { 28533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String accountSelection = RawContactsColumns.CONCRETE_ID + "=? AND " 28543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_NAME + "=? AND " 28553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + "=?"; 28563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String noAccountSelection = RawContactsColumns.CONCRETE_ID + "=? AND " 28573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL AND " 28583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL"; 28593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Cursor c; 28603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (account != null) { 28615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro c = mActiveDb.get().query(Tables.RAW_CONTACTS, 28625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{RawContactsColumns.CONCRETE_ID}, accountSelection, 28633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(rawContactId), mAccount.name, mAccount.type}, 28643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 28653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } else { 28665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro c = mActiveDb.get().query(Tables.RAW_CONTACTS, 28675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{RawContactsColumns.CONCRETE_ID}, noAccountSelection, 28685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{String.valueOf(rawContactId)}, 28693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 28703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 28723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if(c.getCount() == 0) { 28733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann throw new SecurityException("Caller account does not match raw contact ID " 28743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + rawContactId); 28753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 28773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 28783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 28813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 28823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given selection of stream items matches up with the given 28833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account. If any of the raw contacts fail the account check, this will throw a 28843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * security exception. 28853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 28863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selection The selection. 28873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selectionArgs The selection arguments. 28883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The list of stream item IDs that would be included in this selection. 28893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 28903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private List<Long> enforceModifyingAccountForStreamItems(Account account, String selection, 28913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 28923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemIds = Lists.newArrayList(); 28933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 28943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 28955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), 28963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{StreamItems._ID, StreamItems.RAW_CONTACT_ID}, 28973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selection, selectionArgs, null, null, null); 28983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 28993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.moveToNext()) { 29003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann streamItemIds.add(c.getLong(0)); 29013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Throw a security exception if the account doesn't match the raw contact's. 29033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, c.getLong(1)); 29043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 29063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 29073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemIds; 29093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 29123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given selection of stream item photos matches up with the given 29133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account. If any of the raw contacts fail the account check, this will throw a 29143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * security exception. 29153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 29163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selection The selection. 29173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selectionArgs The selection arguments. 29183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The list of stream item photo IDs that would be included in this selection. 29193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 29203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private List<Long> enforceModifyingAccountForStreamItemPhotos(Account account, String selection, 29213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 29223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemPhotoIds = Lists.newArrayList(); 29233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 29243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 29255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), 29265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{StreamItemPhotos._ID, StreamItems.RAW_CONTACT_ID}, 29273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selection, selectionArgs, null, null, null); 29283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 29293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.moveToNext()) { 29303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann streamItemPhotoIds.add(c.getLong(0)); 29313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Throw a security exception if the account doesn't match the raw contact's. 29333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, c.getLong(1)); 29343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 29363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 29373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemPhotoIds; 29393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 29423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Queries the database for stream items under the given raw contact. If there are 29433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * more entries than {@link ContactsProvider2#MAX_STREAM_ITEMS_PER_RAW_CONTACT}, 29443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the oldest entries (as determined by timestamp) will be deleted. 29453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param rawContactId The raw contact ID to examine for stream items. 29463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param insertedStreamItemId The ID of the stream item that was just inserted, 29473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * prompting this cleanup. Callers may pass 0 if no insertion prompted the 29483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * cleanup. 29493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The ID of the inserted stream item if it still exists after cleanup; 29503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 0 otherwise. 29513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 29523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long cleanUpOldStreamItems(long rawContactId, long insertedStreamItemId) { 29533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long postCleanupInsertedStreamId = insertedStreamItemId; 29545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, new String[]{StreamItems._ID}, 29553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItems.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)}, 29563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, StreamItems.TIMESTAMP + " DESC, " + StreamItems._ID + " DESC"); 29573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 29583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann int streamItemCount = c.getCount(); 29593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (streamItemCount <= MAX_STREAM_ITEMS_PER_RAW_CONTACT) { 29603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Still under the limit - nothing to clean up! 29613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return insertedStreamItemId; 29623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } else { 29633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.moveToLast(); 29643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.getPosition() >= MAX_STREAM_ITEMS_PER_RAW_CONTACT) { 29653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long streamItemId = c.getLong(0); 29663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (insertedStreamItemId == streamItemId) { 29673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // The stream item just inserted is being deleted. 29683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann postCleanupInsertedStreamId = 0; 29693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItem(c.getLong(0)); 29713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.moveToPrevious(); 29723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 29753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 29763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return postCleanupInsertedStreamId; 29783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29809261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 298120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 298220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2983f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 298420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 298520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2986de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2987de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 29880c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro Uri dataUri = inProfileMode() 29890c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro ? Uri.withAppendedPath(Profile.CONTENT_URI, RawContacts.Data.CONTENT_DIRECTORY) 29900c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro : Data.CONTENT_URI; 29910c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro Cursor c = query(dataUri, DataRowHandler.DataDeleteQuery.COLUMNS, 2992f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov selection, selectionArgs, null); 2993de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 2994de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 2995f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov long rawContactId = c.getLong(DataRowHandler.DataDeleteQuery.RAW_CONTACT_ID); 2996f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE); 2997a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 29985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro count += rowHandler.delete(mActiveDb.get(), mTransactionContext.get(), c); 2999f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 30005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().markRawContactDirty(rawContactId); 300188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 300220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 300320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 3004de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 300520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 300620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 300720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 300820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 300920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 301088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 301188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 301288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 301320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 3014f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 301588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 301688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 30174da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 3018f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataRowHandler.DataDeleteQuery.COLUMNS, Data._ID + "=?", 30194da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null); 3020f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 302120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 302220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 302320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 302420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 302520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3026f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE); 302720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 302820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 302920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 303020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 303120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 303220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 303320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 303420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 303520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 30367a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 303720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 303820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3039a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 30405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return rowHandler.delete(mActiveDb.get(), mTransactionContext.get(), c); 304120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 304220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 304320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 304420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 304520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 304620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 3047ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 3048ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 3049f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 3050f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 3051f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 3052f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 30533593682b8d9213fde576a0cff54458ad50563980Dave Santoro final AccountWithDataSet accountWithDataSet = resolveAccountWithDataSet(uri, mValues); 3054ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3055ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 3056f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String packageName = mValues.getAsString(Groups.RES_PACKAGE); 305767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 30585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.get().getPackageId(packageName)); 305967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 3060f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.remove(Groups.RES_PACKAGE); 3061ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3062dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final boolean isFavoritesGroup = mValues.getAsLong(Groups.FAVORITES) != null 3063dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ? mValues.getAsLong(Groups.FAVORITES) != 0 3064dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana : false; 3065dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3066f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 3067f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(Groups.DIRTY, 1); 306873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 306973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 30705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long result = mActiveDb.get().insert(Tables.GROUPS, Groups.TITLE, mValues); 3071ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 3072dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && isFavoritesGroup) { 3073dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // add all starred raw contacts to this group 3074dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String selection; 3075dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs; 30763593682b8d9213fde576a0cff54458ad50563980Dave Santoro if (accountWithDataSet == null) { 3077dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + " IS NULL AND " 307843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.ACCOUNT_TYPE + " IS NULL AND " 307943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.DATA_SET + " IS NULL"; 3080dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selectionArgs = null; 30813593682b8d9213fde576a0cff54458ad50563980Dave Santoro } else if (accountWithDataSet.getDataSet() == null) { 3082dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + "=? AND " 30833593682b8d9213fde576a0cff54458ad50563980Dave Santoro + RawContacts.ACCOUNT_TYPE + "=? AND " 30843593682b8d9213fde576a0cff54458ad50563980Dave Santoro + RawContacts.DATA_SET + " IS NULL"; 30853593682b8d9213fde576a0cff54458ad50563980Dave Santoro selectionArgs = new String[] { 30863593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountName(), 30873593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountType() 30883593682b8d9213fde576a0cff54458ad50563980Dave Santoro }; 308943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } else { 309043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro selection = RawContacts.ACCOUNT_NAME + "=? AND " 309143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.ACCOUNT_TYPE + "=? AND " 309243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.DATA_SET + "=?"; 30933593682b8d9213fde576a0cff54458ad50563980Dave Santoro selectionArgs = new String[] { 30943593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountName(), 30953593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountType(), 30963593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getDataSet() 30973593682b8d9213fde576a0cff54458ad50563980Dave Santoro }; 3098dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 30995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, 3100dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{RawContacts._ID, RawContacts.STARRED}, 3101dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection, selectionArgs, null, null, null); 3102892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov try { 3103892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov while (c.moveToNext()) { 3104892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (c.getLong(1) != 0) { 3105892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov final long rawContactId = c.getLong(0); 3106892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov insertDataGroupMembership(rawContactId, result); 31075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().markRawContactDirty(rawContactId); 3108892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 3109dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3110892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } finally { 3111892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov c.close(); 3112dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3113dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3114dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3115f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mValues.containsKey(Groups.GROUP_VISIBLE)) { 31161a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3117ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 3118ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 3119ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 3120ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3121ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 31225aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 3123f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro // Before inserting, ensure that no settings record already exists for the 3124f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro // values being inserted (this used to be enforced by a primary key, but that no 3125f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro // longer works with the nullable data_set field added). 3126f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro String accountName = values.getAsString(Settings.ACCOUNT_NAME); 3127f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro String accountType = values.getAsString(Settings.ACCOUNT_TYPE); 3128f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro String dataSet = values.getAsString(Settings.DATA_SET); 3129f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro Uri.Builder settingsUri = Settings.CONTENT_URI.buildUpon(); 3130f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (accountName != null) { 3131f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro settingsUri.appendQueryParameter(Settings.ACCOUNT_NAME, accountName); 3132f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3133f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (accountType != null) { 3134f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro settingsUri.appendQueryParameter(Settings.ACCOUNT_TYPE, accountType); 3135f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3136f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (dataSet != null) { 3137f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro settingsUri.appendQueryParameter(Settings.DATA_SET, dataSet); 3138f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3139f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro Cursor c = queryLocal(settingsUri.build(), null, null, null, null, 0); 3140f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro try { 3141f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (c.getCount() > 0) { 3142f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro throw new SQLiteConstraintException("Can't insert a settings record with the same " 3143f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + "account name/type/data set"); 3144f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3145f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } finally { 3146f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro c.close(); 3147f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3148f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro 3149f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro // If we didn't find a duplicate, we're fine to insert. 31505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long id = mActiveDb.get().insert(Tables.SETTINGS, null, values); 31515aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 31521a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 31531a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3154e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 31551a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 3156e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 3157e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3158e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3159ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 316082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 31611f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 316282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 316382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 31640a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 31654dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 31664dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 31670a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 316882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 31694dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 31704dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 31714dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 31724dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 31731f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 31741f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3175dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 3176dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 317782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 31786802030a777c0c3ba1dc029c534cca4784260632Dave Santoro String accountType = null; 31796802030a777c0c3ba1dc029c534cca4784260632Dave Santoro String accountName = null; 3180f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 31812526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.clear(); 3182dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 3183dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 3184dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 31852526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "=?"); 31862526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(dataId)); 31871f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 3188dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 3189dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 31900a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 31910a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 31920a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 31930a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3194dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 3195dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 3196dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 31975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String mimeTypeIdIm = String.valueOf(mDbHelper.get().getMimeTypeIdForIm()); 3198dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 31995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String mimeTypeIdEmail = String.valueOf(mDbHelper.get().getMimeTypeIdForEmail()); 3200f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3201f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 3202f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 3203f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 3204f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3205f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 3206f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 32072526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (?,?)" + 32082526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Data.DATA1 + "=?" + 32092526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND ((" + DataColumns.MIMETYPE_ID + "=? AND " + Im.PROTOCOL + "=?"); 32102526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 32112526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32122526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 32132526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32142526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 3215dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 32162526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 32172526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3218dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 32192526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=?))"); 32202526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 3221dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 32222526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=?" + 32232526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.PROTOCOL + "=?" + 32242526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.DATA + "=?"); 32252526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32262526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 32272526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 3228dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 32292526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 32302526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3231dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 3232dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 32331f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 323482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 32352526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=?"); 32362526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(values.getAsString(StatusUpdates.DATA_ID)); 3237dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 323870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 323970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 32401f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 32411f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 32425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro cursor = mActiveDb.get().query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 32432526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.toString(), mSelectionArgs.toArray(EMPTY_STRING_ARRAY), null, null, 32444394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov Clauses.CONTACT_VISIBLE + " DESC, " + Data.RAW_CONTACT_ID); 32451f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 324667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 32475ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 32486802030a777c0c3ba1dc029c534cca4784260632Dave Santoro accountType = cursor.getString(DataContactsQuery.ACCOUNT_TYPE); 32496802030a777c0c3ba1dc029c534cca4784260632Dave Santoro accountName = cursor.getString(DataContactsQuery.ACCOUNT_NAME); 3250e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 32511f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 32521f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 32531f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 32541f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 32551f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 325631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 325731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 325831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 32591f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 32601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 326182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 3262a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 3263a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 3264a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 3265a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 3266a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3267a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3268a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 326982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 3270a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 3271a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 327282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 327382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 327482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 327582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 327682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 3277a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 327882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 327982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 3280aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori mValues.put(StatusUpdates.CHAT_CAPABILITY, 3281aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori values.getAsString(StatusUpdates.CHAT_CAPABILITY)); 32821f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3283a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 32845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().replace(Tables.PRESENCE, null, mValues); 3285a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3286e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 32870a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 328882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 328982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 32900a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 32910bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Resources resources = getContext().getResources(); 32920bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if (!TextUtils.isEmpty(resPackage)) { 32930bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann PackageManager pm = getContext().getPackageManager(); 32940bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann try { 32950bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann resources = pm.getResourcesForApplication(resPackage); 32960bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } catch (NameNotFoundException e) { 32970bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Log.w(TAG, "Contact status update resource package not found: " 32980bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + resPackage); 32990bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 33000bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 33010bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Integer labelResourceId = values.getAsInteger(StatusUpdates.STATUS_LABEL); 33020a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 33030bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if ((labelResourceId == null || labelResourceId == 0) && protocol != null) { 33040bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann labelResourceId = Im.getProtocolLabelResource(protocol); 33050a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 33060bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann String labelResource = getResourceName(resources, "string", labelResourceId); 33070a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 33080bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Integer iconResourceId = values.getAsInteger(StatusUpdates.STATUS_ICON); 33090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 33100a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 33110bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann String iconResource = getResourceName(resources, "drawable", iconResourceId); 33120bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 3313a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 33145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().deleteStatusUpdate(dataId); 3315a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 33166802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 33176802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (timestamp != null) { 33185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().replaceStatusUpdate(dataId, timestamp, status, resPackage, 33190bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann iconResourceId, labelResourceId); 33206802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } else { 33215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().insertStatusUpdate(dataId, status, resPackage, iconResourceId, 33220bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann labelResourceId); 33236802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 33246802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 33256802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // For forward compatibility with the new stream item API, insert this status update 33266802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // there as well. If we already have a stream item from this source, update that 33276802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // one instead of inserting a new one (since the semantics of the old status update 33286802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // API is to only have a single record). 33296802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (rawContactId != -1 && !TextUtils.isEmpty(status)) { 33306802030a777c0c3ba1dc029c534cca4784260632Dave Santoro ContentValues streamItemValues = new ContentValues(); 33316802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RAW_CONTACT_ID, rawContactId); 3332d5ef5903570e533a501abe6a8e3d533fdb5318fcFlavio Lerda // Status updates are text only but stream items are HTML. 3333e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda streamItemValues.put(StreamItems.TEXT, statusUpdateToHtml(status)); 33346802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.COMMENTS, ""); 33356802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RES_PACKAGE, resPackage); 33366802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RES_ICON, iconResource); 33376802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RES_LABEL, labelResource); 33386802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.TIMESTAMP, 33396802030a777c0c3ba1dc029c534cca4784260632Dave Santoro timestamp == null ? System.currentTimeMillis() : timestamp); 33406802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 33416802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Note: The following is basically a workaround for the fact that status 33426802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // updates didn't do any sort of account enforcement, while social stream item 33436802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // updates do. We can't expect callers of the old API to start passing account 33446802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // information along, so we just populate the account params appropriately for 334543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // the raw contact. Data set is not relevant here, as we only check account 334643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // name and type. 33476802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (accountName != null && accountType != null) { 33486802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(RawContacts.ACCOUNT_NAME, accountName); 33496802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(RawContacts.ACCOUNT_TYPE, accountType); 33506802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 33516802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 33526802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Check for an existing stream item from this source, and insert or update. 33536802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Uri streamUri = StreamItems.CONTENT_URI; 33546802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Cursor c = query(streamUri, new String[]{StreamItems._ID}, 33556802030a777c0c3ba1dc029c534cca4784260632Dave Santoro StreamItems.RAW_CONTACT_ID + "=?", 33566802030a777c0c3ba1dc029c534cca4784260632Dave Santoro new String[]{String.valueOf(rawContactId)}, null); 33576802030a777c0c3ba1dc029c534cca4784260632Dave Santoro try { 33586802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (c.getCount() > 0) { 33596802030a777c0c3ba1dc029c534cca4784260632Dave Santoro c.moveToFirst(); 33606802030a777c0c3ba1dc029c534cca4784260632Dave Santoro update(ContentUris.withAppendedId(streamUri, c.getLong(0)), 33616802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues, null, null); 33626802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } else { 33636802030a777c0c3ba1dc029c534cca4784260632Dave Santoro insert(streamUri, streamItemValues); 33646802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 33656802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } finally { 33666802030a777c0c3ba1dc029c534cca4784260632Dave Santoro c.close(); 33676802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 33686802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 3369e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3370e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3371bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 3372a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 33735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateLastStatusUpdateId(contactId); 3374a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3375a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3376a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 33771f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 33781f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3379e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda /** Converts a status update to HTML. */ 3380e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda private String statusUpdateToHtml(String status) { 33814747809486541f7a3d342d3e1dd48fb5ea255ad6Flavio Lerda return TextUtils.htmlEncode(status); 3382e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda } 3383e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda 33840bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann private String getResourceName(Resources resources, String expectedType, Integer resourceId) { 33850bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann try { 33860bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if (resourceId == null || resourceId == 0) return null; 33870bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 33880bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann // Resource has an invalid type (e.g. a string as icon)? ignore 33890bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann final String resourceEntryName = resources.getResourceEntryName(resourceId); 33900bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann final String resourceTypeName = resources.getResourceTypeName(resourceId); 33910bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if (!expectedType.equals(resourceTypeName)) { 33920bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Log.w(TAG, "Resource " + resourceId + " (" + resourceEntryName + ") is of type " + 33930bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann resourceTypeName + " but " + expectedType + " is required."); 33940bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann return null; 33950bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 33960bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 33970bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann return resourceEntryName; 33980bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } catch (NotFoundException e) { 33990bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann return null; 34000bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 34010bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 34020bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 34034f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3404de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 3405bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3406b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 3407b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 34085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 34095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 34105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 34115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 34125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 34135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 3414b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3415f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3416f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 3417508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 3418508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 341935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 34205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 34215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().delete(mActiveDb.get(), selection, 34225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 34235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 34245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case SYNCSTATE_ID: { 34255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String selectionWithId = 34265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 34275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro + (selection == null ? "" : " AND (" + selection + ")"); 34285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().delete(mActiveDb.get(), selectionWithId, 34295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 34305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 343135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 34325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE_ID: { 3433b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3434b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3435b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 34365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileHelper.getSyncState().delete(mActiveDb.get(), selectionWithId, 34375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 34385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 3439b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3440cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 3441cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 3442cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 3443cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3444cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3445d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3446d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3447dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 34486bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 34496bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 34509fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP: { 34512e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 34522e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 34532e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 34545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 3455fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 34562e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 34572e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 34585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 3459dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 34602e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 34612e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 34629fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP_ID: { 34639fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // lookup contact by id and lookup key to see if they still match the actual record 34649fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final List<String> pathSegments = uri.getPathSegments(); 34659fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final String lookupKey = pathSegments.get(2); 34669fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 34679fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann setTablesAndProjectionMapForContacts(lookupQb, uri, null); 3468a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 34699fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann String[] args; 34709fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (selectionArgs == null) { 34719fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[2]; 34729fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 34739fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[selectionArgs.length + 2]; 34749fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 34759fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34769fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args[0] = String.valueOf(contactId); 347760de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann args[1] = Uri.encode(lookupKey); 34789fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 34795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = query(mActiveDb.get(), lookupQb, null, selection, args, null, null, 34805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro null); 34819fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann try { 34829fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (c.getCount() == 1) { 34839fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // contact was unmodified so go ahead and delete it 3484dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 34859fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 34869fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // row was changed (e.g. the merging might have changed), we got multiple 34879fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // rows or the supplied selection filtered the record out 34889fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return 0; 34899fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34909fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } finally { 34919fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann c.close(); 34929fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34939fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34949fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 3495d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS: 3496d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS: { 34972971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 34985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, 3499fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov new String[]{RawContacts._ID, RawContacts.CONTACT_ID}, 3500e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 35012971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 35022971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 35032971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 3504fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov long contactId = c.getLong(1); 3505fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov numDeletes += deleteRawContact(rawContactId, contactId, 3506fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 35072971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35082971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 35092971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 35102971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35112971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 35122971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35132971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 3514d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_ID: 3515d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID: { 35162971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 35175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return deleteRawContact(rawContactId, mDbHelper.get().getContactId(rawContactId), 3518fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 3519508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3520508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 35210c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case DATA: 35220c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case PROFILE_DATA: { 3523f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 3524944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 3525f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 352620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 352720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 352848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 352948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 353048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 3531d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case POSTALS_ID: 3532d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_DATA_ID: { 3533508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 3534f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 35354da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 35364da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return deleteData(Data._ID + "=?", mSelectionArgs1, callerIsSyncAdapter); 3537ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3538ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3539ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3540f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 35415aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 35422971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35432971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 35442971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 35452971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 35465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.GROUPS, new String[]{Groups._ID}, 3547e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 35482971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 35492971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 35505aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 35512971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35522971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 35532971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 35542971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 355581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 3556f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 355781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 35582971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 3559508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3560508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 3561eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 356243880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3563e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return deleteSettings(uri, appendAccountToSelection(uri, selection), selectionArgs); 3564eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3565eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 35665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 35675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 35680a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 35691f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 35701f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 35713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 35723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 35733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItems(uri, new ContentValues(), selection, selectionArgs); 35743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 35753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 35763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 35773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 35783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItems(uri, new ContentValues(), 35799b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann StreamItems._ID + "=?", 35803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{uri.getLastPathSegment()}); 35813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 35823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 358382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro case RAW_CONTACTS_ID_STREAM_ITEMS_ID: { 358482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro mSyncToNetwork |= !callerIsSyncAdapter; 358582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String rawContactId = uri.getPathSegments().get(1); 358682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String streamItemId = uri.getLastPathSegment(); 358782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro return deleteStreamItems(uri, new ContentValues(), 358882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems.RAW_CONTACT_ID + "=? AND " + StreamItems._ID + "=?", 358982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro new String[]{rawContactId, streamItemId}); 359082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 359182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 359282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 35933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 35943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 35955d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro String streamItemId = uri.getPathSegments().get(1); 35965d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro String selectionWithId = 35975d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro (StreamItemPhotos.STREAM_ITEM_ID + "=" + streamItemId + " ") 35985d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro + (selection == null ? "" : " AND (" + selection + ")"); 35995d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro return deleteStreamItemPhotos(uri, new ContentValues(), 36005d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro selectionWithId, selectionArgs); 36013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 36023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 36033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 36043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 36053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 36063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 36073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItemPhotos(uri, new ContentValues(), 36083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=? AND " 36093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + StreamItemPhotos.STREAM_ITEM_ID + "=?", 36103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{streamItemPhotoId, streamItemId}); 36113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 36123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 361381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 361481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 36153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 361681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3617508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 36184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 36194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 36201c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 3621ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 36225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long groupMembershipMimetypeId = mDbHelper.get() 362394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 36245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 362594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 362694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 362794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 362894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 3629f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 36305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 363194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 363294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 363394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 3634f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 36355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, 36365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro null); 363794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 363894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 36391a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 364094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 364194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 364294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 36435aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 36445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final int count = mActiveDb.get().delete(Tables.SETTINGS, selection, selectionArgs); 36451a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3646e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3647e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3648e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3649dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int deleteContact(long contactId, boolean callerIsSyncAdapter) { 365096b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(contactId); 36515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 365296b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker RawContacts.CONTACT_ID + "=?", mSelectionArgs1, 365396b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker null, null, null); 3654cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 3655cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 3656cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 3657dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 3658cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3659cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 3660cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 3661cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3662cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 36633826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 36643826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 36655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 3666cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3667cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3668fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) { 36695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().invalidateAggregationExceptionCache(); 36703826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 36713826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 367282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro // Find and delete stream items associated with the raw contact. 367382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, 367482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro new String[]{StreamItems._ID}, 367582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)}, 367682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro null, null, null); 367782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro try { 367882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro while (c.moveToNext()) { 367982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro deleteStreamItem(c.getLong(0)); 368082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 368182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } finally { 368282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro c.close(); 368382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 368482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 3685d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro if (callerIsSyncAdapter || rawContactIsLocal(rawContactId)) { 36865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.PRESENCE, 36875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 36885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int count = mActiveDb.get().delete(Tables.RAW_CONTACTS, 36895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro RawContacts._ID + "=" + rawContactId, null); 36905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateDisplayNameForContact(mActiveDb.get(), contactId); 3691fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return count; 369233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 36935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().removeContactIfSingleton(rawContactId); 3694dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 369533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 369633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 369733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 3698d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro /** 3699d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro * Returns whether the given raw contact ID is local (i.e. has no account associated with it). 3700d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro */ 3701d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro private boolean rawContactIsLocal(long rawContactId) { 3702d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, 3703d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro new String[] { 3704d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro RawContacts.ACCOUNT_NAME, 3705d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro RawContacts.ACCOUNT_TYPE, 3706d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro RawContacts.DATA_SET 3707d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro }, 3708d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro RawContacts._ID + "=?", 3709d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro new String[] {String.valueOf(rawContactId)}, null, null, null); 3710d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro try { 3711d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro return c.moveToFirst() && c.isNull(0) && c.isNull(1) && c.isNull(2); 3712d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro } finally { 3713d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro c.close(); 3714d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro } 3715d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro } 3716d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro 37170a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 37189705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // delete from both tables: presence and status_updates 37199705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 37209705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (VERBOSE_LOGGING) { 37219705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Log.v(TAG, "deleting data from status_updates for " + selection); 37229705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 37235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 37249705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 37255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.PRESENCE, selection, selectionArgs); 37260a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 37270a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 37283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItems(Uri uri, ContentValues values, String selection, 37293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 37303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // First query for the stream items to be deleted, and check that they belong 37313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // to the account. 37323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 37333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemIds = enforceModifyingAccountForStreamItems( 37343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann account, selection, selectionArgs); 37353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If no security exception has been thrown, we're fine to delete. 37373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann for (long streamItemId : streamItemIds) { 37383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItem(streamItemId); 37393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mVisibleTouched = true; 37423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemIds.size(); 37433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItem(long streamItemId) { 37463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Note that this does not enforce the modifying account. 37473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItemPhotos(streamItemId); 37485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.STREAM_ITEMS, StreamItems._ID + "=?", 37493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(streamItemId)}); 37503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItemPhotos(Uri uri, ContentValues values, String selection, 37533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 37543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // First query for the stream item photos to be deleted, and check that they 37553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // belong to the account. 37563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 37573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItemPhotos(account, selection, selectionArgs); 37583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If no security exception has been thrown, we're fine to delete. 37605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.STREAM_ITEM_PHOTOS, selection, selectionArgs); 37613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItemPhotos(long streamItemId) { 37643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Note that this does not enforce the modifying account. 37655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.STREAM_ITEM_PHOTOS, 37665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro StreamItemPhotos.STREAM_ITEM_ID + "=?", 37673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(streamItemId)}); 37683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 3770dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int markRawContactAsDeleted(long rawContactId, boolean callerIsSyncAdapter) { 377181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 377281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 3773cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 3774cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 3775cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 3776cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 3777cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 3778cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3779dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return updateRawContact(rawContactId, mValues, callerIsSyncAdapter); 3780cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3781cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 37824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3783de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 3784de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 3785bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3786b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 3787b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3788b5a4add17815167d20a90645779df34cdf45280dFred Quintana 37895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 37905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 37915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 37925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 37935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 379435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 379500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 379600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 3797b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 3798b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 37991129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Object data = values.get(ContactsContract.SyncState.DATA); 38005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().syncStateUpdated(rowId, data); 3801b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 3802b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3803b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3804f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3805f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 380600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 380735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 38085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 38095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().update(mActiveDb.get(), values, 3810b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 3811b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3812b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 3813b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 3814b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3815b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3816b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 38175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().update(mActiveDb.get(), values, 38185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionWithId, selectionArgs); 38195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 38205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 38215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE_ID: { 38225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection = appendAccountToSelection(uri, selection); 38235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String selectionWithId = 38245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 38255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro + (selection == null ? "" : " AND (" + selection + ")"); 38265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileHelper.getSyncState().update(mActiveDb.get(), values, 3827b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 3828b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 382935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3830d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case CONTACTS: 3831d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE: { 3832dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(values, selection, selectionArgs, callerIsSyncAdapter); 383300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 383400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 383500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3836d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3837dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(ContentUris.parseId(uri), values, callerIsSyncAdapter); 3838c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 3839c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 3840c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 38412e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 38422e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 38432e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 38442e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 38452e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 38465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 3847fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 38482e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 38492e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 38505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 3851dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(contactId, values, callerIsSyncAdapter); 38522e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 38532e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 38542e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 3855d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_DATA: 3856d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID_DATA: { 3857d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro int segment = match == RAW_CONTACTS_DATA ? 1 : 2; 3858d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro final String rawContactId = uri.getPathSegments().get(segment); 38597d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 38607d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 38617d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 38627d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 38637d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 38647d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 38657d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 38667d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 38670c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case DATA: 38680c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case PROFILE_DATA: { 3869944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 3870f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 387181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3872f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 387381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 387420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 387520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3876c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 387748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 387848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 387948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 388048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3881f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 388281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3883f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 388481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 388500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 388600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 38877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 38885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case RAW_CONTACTS: 38895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_RAW_CONTACTS: { 38905ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 3891dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, selection, selectionArgs, callerIsSyncAdapter); 38927e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 38937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 38947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 38955ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 389633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 38974529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 38984da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 38994da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?" 3900dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND(" + selection + ")", selectionArgs, 3901dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 39024529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 39034da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 3904dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, RawContacts._ID + "=?", mSelectionArgs1, 3905dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 39064529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 39077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 39087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3910ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 39115aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 3912f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 391381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3914f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 391581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3916ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3917ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3918ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3919ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3920ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 39214da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(groupId)); 39224da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String selectionWithId = Groups._ID + "=? " 392373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 39245aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 39255aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 392681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3927f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 392881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3929ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3930ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3931ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3932127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 39335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro count = updateAggregationException(mActiveDb.get(), values); 3934b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3935b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3936b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3937eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3938e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey count = updateSettings(uri, values, appendAccountToSelection(uri, selection), 3939e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey selectionArgs); 394043880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3941eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3942eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3943eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 39445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 39455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 39469705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori count = updateStatusUpdate(uri, values, selection, selectionArgs); 39479705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori break; 39489705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 39499705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 39503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 39513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItems(uri, values, selection, selectionArgs); 39523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 39553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 39569b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann count = updateStreamItems(uri, values, StreamItems._ID + "=?", 39573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{uri.getLastPathSegment()}); 39583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 396182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro case RAW_CONTACTS_ID_STREAM_ITEMS_ID: { 396282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String rawContactId = uri.getPathSegments().get(1); 396382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String streamItemId = uri.getLastPathSegment(); 396482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro count = updateStreamItems(uri, values, 396582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems.RAW_CONTACT_ID + "=? AND " + StreamItems._ID + "=?", 396682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro new String[]{rawContactId, streamItemId}); 396782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro break; 396882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 396982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 39703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 39713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, selection, selectionArgs); 39723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 39753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 39763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 39773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, 39783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotos.STREAM_ITEM_ID + "=?", new String[]{streamItemId}); 39793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 39823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 39833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 39843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 39853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, 39863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=? AND " + 39873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=?", 39883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{streamItemPhotoId, streamItemId}); 39893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 399272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case DIRECTORIES: { 3993bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.scanPackagesByUid(Binder.getCallingUid()); 399472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov count = 1; 3995d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 3996d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3997d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 399846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa case DATA_USAGE_FEEDBACK_ID: { 399946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (handleDataUsageFeedback(uri)) { 400046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa count = 1; 400146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 400246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa count = 0; 400346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 400446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa break; 400546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 400646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 400781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 400881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 4009f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 401081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 401100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 401200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 401300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 40144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 40154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 40169705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 40179705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori String[] selectionArgs) { 40189705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // update status_updates table, if status is provided 40199705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 40209705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori int updateCount = 0; 40219705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 40229705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 40235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro updateCount = mActiveDb.get().update(Tables.STATUS_UPDATES, 40249705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues, 40259705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori getWhereClauseForStatusUpdatesTable(selection), 40269705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 40279705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40289705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 40299705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // now update the Presence table 40309705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues = getSettableColumnsForPresenceTable(values); 40319705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 40325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro updateCount = mActiveDb.get().update(Tables.PRESENCE, settableValues, 40339705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selection, selectionArgs); 40349705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40359705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 40369705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // potentially get updated in this method. 40379705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return updateCount; 40389705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40399705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 40403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int updateStreamItems(Uri uri, ContentValues values, String selection, 40413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 40423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Stream items can't be moved to a new raw contact. 40433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.remove(StreamItems.RAW_CONTACT_ID); 40443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check that the stream items being updated belong to the account. 40463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 40473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItems(account, selection, selectionArgs); 40483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40496802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to update accounts params - they don't exist in the stream items table. 40506802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_NAME); 40516802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_TYPE); 40526802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 40533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If there's been no exception, the update should be fine. 40545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().update(Tables.STREAM_ITEMS, values, selection, selectionArgs); 40553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 40563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int updateStreamItemPhotos(Uri uri, ContentValues values, String selection, 40583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 40593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Stream item photos can't be moved to a new stream item. 40603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.remove(StreamItemPhotos.STREAM_ITEM_ID); 40613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check that the stream item photos being updated belong to the account. 40633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 40643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItemPhotos(account, selection, selectionArgs); 40653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40666802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to update accounts params - they don't exist in the stream item 40676802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // photos table. 40686802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_NAME); 40696802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_TYPE); 40706802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 40716802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Process the photo (since we're updating, it's valid for the photo to not be present). 40726802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (processStreamItemPhoto(values, true)) { 40736802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // If there's been no exception, the update should be fine. 40745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().update(Tables.STREAM_ITEM_PHOTOS, values, selection, 40755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 40766802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 40776802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return 0; 40783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 40793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40809705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 40819705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Build a where clause to select the rows to be updated in status_updates table. 40829705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 40839705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private String getWhereClauseForStatusUpdatesTable(String selection) { 40849705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.setLength(0); 40859705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 40869705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(selection); 40879705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(")"); 40889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mSb.toString(); 40899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 40919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 40929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 40939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 40949705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS); 40959705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 40969705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_TIMESTAMP); 40979705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 40989705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_RES_PACKAGE); 40999705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 41009705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_LABEL); 41019705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 41029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_ICON); 41039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 41049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 41059705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 41069705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 41079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 41089705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 41099705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.PRESENCE); 4110aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.CHAT_CAPABILITY, values, 4111aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori StatusUpdates.CHAT_CAPABILITY); 41129705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 41139705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 41149705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 41155aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 4116f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 411773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 4118ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 4119ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 412073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 4121f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 412273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 412373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 412473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 412573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 412673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 412773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 412873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 412973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 41305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int count = mActiveDb.get().update(Tables.GROUPS, updatedValues, selectionWithId, 41315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 41321a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 41331a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 413494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 413543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 413643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // TODO: This will not work for groups that have a data set specified, since the content 413743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // resolver will not be able to request a sync for the right source (unless it is updated 413843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // to key off account with data set). 41396ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 41401129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 41415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 4142e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey Groups.ACCOUNT_TYPE}, selectionWithId, selectionArgs, null, 41436ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 41446ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 41456ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 41466ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 41476ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 41486ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 41496ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 415024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 41516ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 4152ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 41536ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 41546ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 41556ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 41566ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 41576ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 41586ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 41596ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 41606ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 416194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 416294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 416394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 4164b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 4165b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 41665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final int count = mActiveDb.get().update(Tables.SETTINGS, values, selection, selectionArgs); 41671a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 41681a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 4169e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4170e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 4171e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4172e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4173dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs, 4174dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 41754529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 41764529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 41774529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 41784529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 417973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 418097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 418197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 418297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0"); 418397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 418497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 41854529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 41865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(Views.RAW_CONTACTS, 418751bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 41884529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 41894529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 41904529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 41914529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 4192dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateRawContact(rawContactId, values, callerIsSyncAdapter); 41934529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 41944529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 41954529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 41964529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 41974529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 41984529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 41994529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 42004529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 42014529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 4202dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContact(long rawContactId, ContentValues values, 4203dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 420496b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker final String selection = RawContacts._ID + " = ?"; 420596b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(rawContactId); 420619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 420719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 420819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 4209ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = null; 4210ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = null; 421143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String dataSet = null; 421219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 42135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, 42145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection, mSelectionArgs1, null, null, null); 421519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 421619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 421719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 4218ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 4219ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 422043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro dataSet = cursor.getString(RawContactsQuery.DATA_SET); 422119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 422219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 422319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 422419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 422519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 422619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 422719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 4228f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 42295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int count = mActiveDb.get().update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1); 42305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 4231f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (values.containsKey(RawContacts.AGGREGATION_MODE)) { 4232f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = values.getAsInteger(RawContacts.AGGREGATION_MODE); 4233f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov 4234f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // As per ContactsContract documentation, changing aggregation mode 4235f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // to DEFAULT should not trigger aggregation 4236f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (aggregationMode != RawContacts.AGGREGATION_MODE_DEFAULT) { 42375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markForAggregation(rawContactId, aggregationMode, false); 4238f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 4239f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 4240433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 4241dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 4242dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 4243dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana values.getAsLong(RawContacts.STARRED) != 0); 4244dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 42455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateStarred(rawContactId); 4246dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 4247dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then update the 4248dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // favorites group membership based on whether or not this contact is starred. 4249dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // If it is starred, add a group membership, if one doesn't already exist 4250dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // otherwise delete any matching group memberships. 4251dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 42525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro boolean starred = 0 != DatabaseUtils.longForQuery(mActiveDb.get(), 4253dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana SELECTION_STARRED_FROM_RAW_CONTACTS, 4254dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}); 4255dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred); 4256dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4257dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4258dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 4259dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then add a 4260dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // group membership to the group marked as AutoAdd, if any. 4261dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 4262dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 4263433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 4264dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 4265285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 42665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateLookupKeyForRawContact(mActiveDb.get(), rawContactId); 4267285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 4268f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.containsKey(RawContacts.NAME_VERIFIED)) { 4269f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 4270f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // If setting NAME_VERIFIED for this raw contact, reset it for all 4271f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // other raw contacts in the same aggregate 4272f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.getAsInteger(RawContacts.NAME_VERIFIED) != 0) { 42735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().resetNameVerifiedForOtherRawContacts(rawContactId); 4274f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 42755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateDisplayNameForRawContact(mActiveDb.get(), rawContactId); 4276f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 427719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 42785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().rawContactInserted(rawContactId, 427943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new AccountWithDataSet(accountName, accountType, dataSet)); 428019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 42815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 428333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 428433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 4285321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 4286f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 428720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 428820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 428920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 42905ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 429120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 429220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 429320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 429420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 429520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 42965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(DataColumns.PACKAGE_ID, mDbHelper.get().getPackageId(packageName)); 429720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 429820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 429997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 430097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 430197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov Data.IS_READ_ONLY + "=0"); 430297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 430397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 4304653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 430520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4306653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 4307653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 43085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryLocal(uri, 4309f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro DataRowHandler.DataUpdateQuery.COLUMNS, 43105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection, selectionArgs, null, -1 /* directory ID */); 4311653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 4312653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 4313f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 431420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 4315653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 4316653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 431720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 431820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4319653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 432020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 432120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4322f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 4323653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 4324653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 4325321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 4326653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 4327f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final String mimeType = c.getString(DataRowHandler.DataUpdateQuery.MIMETYPE); 4328a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 4329f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro boolean updated = 43305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro rowHandler.update(mActiveDb.get(), mTransactionContext.get(), values, c, 43315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro callerIsSyncAdapter); 4332f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) { 4333f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS); 4334a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 4335f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return updated ? 1 : 0; 4336321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 4337321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 43388c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 4339dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 43408c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 43415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(Views.CONTACTS, 43425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[] { Contacts._ID }, selection, selectionArgs, null, null, null); 43438c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 43448c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 43458c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 434624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 4347dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateContactOptions(contactId, values, callerIsSyncAdapter); 43488c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 43498c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 43508c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 43518c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 43528c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 43538c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 43548c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 43558c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 43568c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 4357dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateContactOptions(long contactId, ContentValues values, 4358dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 4359d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 43608c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 4361b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 4362d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 4363b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 4364d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 4365b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 4366d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 4367b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 4368d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 4369b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 4370d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 4371d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 4372d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 43738c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 4374d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 4375d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 4376d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 43778c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 4378c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 43798c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 4380c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 4381c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 43824da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 43835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?" 438497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov + " AND " + RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0", mSelectionArgs1); 43858c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 4386dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (mValues.containsKey(RawContacts.STARRED) && !callerIsSyncAdapter) { 43875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(Views.RAW_CONTACTS, 4388dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[] { RawContacts._ID }, RawContacts.CONTACT_ID + "=?", 4389dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mSelectionArgs1, null, null, null); 4390dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 4391dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (cursor.moveToNext()) { 4392dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana long rawContactId = cursor.getLong(0); 4393dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 4394dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.getAsLong(RawContacts.STARRED) != 0); 4395dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4396dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 4397dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana cursor.close(); 4398dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4399dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4400dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 44018c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 44028c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 44038c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 4404b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 44058c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 4406b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 44078c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 4408b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 44098c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 4410b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 44118c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 4412b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 44138c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 44148c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 44155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int rslt = mActiveDb.get().update(Tables.CONTACTS, mValues, Contacts._ID + "=?", 44165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mSelectionArgs1); 44176e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori 44189b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori if (values.containsKey(Contacts.LAST_TIME_CONTACTED) && 44199b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori !values.containsKey(Contacts.TIMES_CONTACTED)) { 44205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 44215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 44229b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori } 44239b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori return rslt; 4424f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 4425d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 4426127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 4427127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 44280c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 44290c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 443080c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 4431ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov long rawContactId1; 4432ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov long rawContactId2; 44330c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 44340c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 44350c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 44360c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 44370c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 44380c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 4439b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4440127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 44410c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 44424da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[0] = String.valueOf(rawContactId1); 44434da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[1] = String.valueOf(rawContactId2); 44440c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 44454da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=? AND " 44464da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=?", mSelectionArgs2); 44470c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 44486bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 44496bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 44500c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 44510c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 44520c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 44530c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 4454127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 4455127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 44565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().invalidateAggregationExceptionCache(); 44575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markForAggregation(rawContactId1, 445869cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 44595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markForAggregation(rawContactId2, 446069cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 4461dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 44625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().aggregateContact(mTransactionContext.get(), db, rawContactId1); 44635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().aggregateContact(mTransactionContext.get(), db, rawContactId2); 4464127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 4465127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 4466127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 4467127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 4468b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4469b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 447070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 4471bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS); 44723826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 44733826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 4474bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected boolean updateAccountsInBackground(Account[] accounts) { 4475f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao // TODO : Check the unit test. 4476e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov boolean accountsChanged = false; 44775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mDbHelper.get().getWritableDatabase(); 44785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(db); 44795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.beginTransaction(); 448070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 448143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Set<AccountWithDataSet> existingAccountsWithDataSets = 448243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro findValidAccountsWithDataSets(Tables.ACCOUNTS); 4483743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov 448443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Add a row to the ACCOUNTS table (with no data set) for each new account. 4485743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov for (Account account : accounts) { 448643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro AccountWithDataSet accountWithDataSet = new AccountWithDataSet( 448743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro account.name, account.type, null); 448843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (!existingAccountsWithDataSets.contains(accountWithDataSet)) { 4489e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 449043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 449143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Add an account entry with an empty data set to match the account. 44925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 449343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ", " + RawContacts.ACCOUNT_TYPE + ", " + RawContacts.DATA_SET 449443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ") VALUES (?, ?, ?)", 449543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new String[] { 449643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 449743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType(), 449843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getDataSet() 449943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }); 4500743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 4501743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 450248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 450343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Check each of the existing sub-accounts against the account list. If the owning 450443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // account no longer exists, the sub-account and all its data should be deleted. 450543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro List<AccountWithDataSet> accountsWithDataSetsToDelete = 450643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new ArrayList<AccountWithDataSet>(); 450743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro List<Account> accountList = Arrays.asList(accounts); 450843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro for (AccountWithDataSet accountWithDataSet : existingAccountsWithDataSets) { 450943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Account owningAccount = new Account( 451043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), accountWithDataSet.getAccountType()); 451143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (!accountList.contains(owningAccount)) { 451243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountsWithDataSetsToDelete.add(accountWithDataSet); 451343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 451470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 451570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 451643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (!accountsWithDataSetsToDelete.isEmpty()) { 4517e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 451843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro for (AccountWithDataSet accountWithDataSet : accountsWithDataSetsToDelete) { 451943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Log.d(TAG, "removing data for removed account " + accountWithDataSet); 452043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String[] accountParams = new String[] { 452143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 452243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType() 452343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }; 452443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String[] accountWithDataSetParams = accountWithDataSet.getDataSet() == null 452543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ? accountParams 452643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro : new String[] { 452743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 452843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType(), 452943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getDataSet() 453043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }; 453143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String groupsDataSetClause = " AND " + Groups.DATA_SET 453243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + (accountWithDataSet.getDataSet() == null ? " IS NULL" : " = ?"); 453343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String rawContactsDataSetClause = " AND " + RawContacts.DATA_SET 453443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + (accountWithDataSet.getDataSet() == null ? " IS NULL" : " = ?"); 4535f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro String settingsDataSetClause = " AND " + Settings.DATA_SET 4536f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + (accountWithDataSet.getDataSet() == null ? " IS NULL" : " = ?"); 453743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 45385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4539e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.GROUPS + 4540e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 454143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + Groups.ACCOUNT_TYPE + " = ?" + 454243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro groupsDataSetClause, accountWithDataSetParams); 45435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4544e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 4545e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 4546e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "SELECT " + RawContacts._ID + 4547e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 4548e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 454943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 455043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactsDataSetClause + ")", accountWithDataSetParams); 45515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4552c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "DELETE FROM " + Tables.STREAM_ITEM_PHOTOS + 4553c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + StreamItemPhotos.STREAM_ITEM_ID + " IN (" + 4554c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "SELECT " + StreamItems._ID + 4555c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " FROM " + Tables.STREAM_ITEMS + 4556c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + StreamItems.RAW_CONTACT_ID + " IN (" + 4557c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "SELECT " + RawContacts._ID + 4558c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " FROM " + Tables.RAW_CONTACTS + 4559c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 4560c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 4561c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro rawContactsDataSetClause + "))", 4562c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro accountWithDataSetParams); 4563c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro db.execSQL( 4564c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "DELETE FROM " + Tables.STREAM_ITEMS + 4565c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + StreamItems.RAW_CONTACT_ID + " IN (" + 4566c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "SELECT " + RawContacts._ID + 4567c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " FROM " + Tables.RAW_CONTACTS + 4568c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 4569c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 4570c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro rawContactsDataSetClause + ")", 4571c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro accountWithDataSetParams); 4572c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro db.execSQL( 4573e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.RAW_CONTACTS + 4574e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 457543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 457643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactsDataSetClause, accountWithDataSetParams); 45775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4578e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 4579e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 4580f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro " AND " + Settings.ACCOUNT_TYPE + " = ?" + 4581f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro settingsDataSetClause, accountWithDataSetParams); 45825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4583e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.ACCOUNTS + 4584e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + "=?" + 458543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + "=?" + 458643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactsDataSetClause, accountWithDataSetParams); 45875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4588d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov "DELETE FROM " + Tables.DIRECTORIES + 4589d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov " WHERE " + Directory.ACCOUNT_NAME + "=?" + 459043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + Directory.ACCOUNT_TYPE + "=?", accountParams); 45914458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov resetDirectoryCache(); 4592e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 4593e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov 459433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // Find all aggregated contacts that used to contain the raw contacts 459533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // we have just deleted and see if they are still referencing the deleted 4596e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov // names or photos. If so, fix up those contacts. 459733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov HashSet<Long> orphanContactIds = Sets.newHashSet(); 45985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = db.rawQuery("SELECT " + Contacts._ID + 459933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " FROM " + Tables.CONTACTS + 460033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " WHERE (" + Contacts.NAME_RAW_CONTACT_ID + " NOT NULL AND " + 460169cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov Contacts.NAME_RAW_CONTACT_ID + " NOT IN " + 460269cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + RawContacts._ID + 460369cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + "))" + 460433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " OR (" + Contacts.PHOTO_ID + " NOT NULL AND " + 460533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Contacts.PHOTO_ID + " NOT IN " + 460669cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + Data._ID + 460769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.DATA + "))", null); 460833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov try { 460933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov while (cursor.moveToNext()) { 461033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov orphanContactIds.add(cursor.getLong(0)); 461133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 461233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } finally { 461333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov cursor.close(); 461433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 461533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 461633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov for (Long contactId : orphanContactIds) { 46175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateAggregateData(mTransactionContext.get(), contactId); 461833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 46195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().updateAllVisible(); 4620bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 462133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 462233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 462343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Now that we've done the account-based additions and subtractions from the Accounts 462443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // table, check for raw contacts that have been added with a data set and add Accounts 462543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // entries for those if necessary. 462643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro existingAccountsWithDataSets = findValidAccountsWithDataSets(Tables.ACCOUNTS); 462743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Set<AccountWithDataSet> rawContactAccountsWithDataSets = 462843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro findValidAccountsWithDataSets(Tables.RAW_CONTACTS); 462943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactAccountsWithDataSets.removeAll(existingAccountsWithDataSets); 463043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 463143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Any remaining raw contact sub-accounts need to be added to the Accounts table. 463243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro for (AccountWithDataSet accountWithDataSet : rawContactAccountsWithDataSets) { 463343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountsChanged = true; 463443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 463543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Add an account entry to match the raw contact. 46365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 463743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ", " + RawContacts.ACCOUNT_TYPE + ", " + RawContacts.DATA_SET 463843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ") VALUES (?, ?, ?)", 463943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new String[] { 464043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 464143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType(), 464243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getDataSet() 464343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }); 464443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 464543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 4646e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov if (accountsChanged) { 464743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // TODO: Should sync state take data set into consideration? 46485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getSyncState().onAccountsChanged(db, accounts); 4649e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 46505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.setTransactionSuccessful(); 465170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 46525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.endTransaction(); 465370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 465473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.clear(); 46553826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 46563826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (accountsChanged) { 46573826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateContactsAccountCount(accounts); 46583826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateProviderStatus(); 46593826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46603826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 4661afb84050536a4472c13efc0e996d31132d254605Dmitri Plotnikov return accountsChanged; 466270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 4663619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 46643826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private void updateContactsAccountCount(Account[] accounts) { 46653826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov int count = 0; 46663826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov for (Account account : accounts) { 46673826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (isContactsAccount(account)) { 46683826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov count++; 46693826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46703826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46713826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mContactsAccountCount = count; 46723826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46733826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 46743826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov protected boolean isContactsAccount(Account account) { 46753826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov final IContentService cs = ContentResolver.getContentService(); 46763826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov try { 46773826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return cs.getIsSyncable(account, ContactsContract.AUTHORITY) > 0; 46783826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } catch (RemoteException e) { 46793826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov Log.e(TAG, "Cannot obtain sync flag for account: " + account, e); 46803826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return false; 46813826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46823826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46833826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 468472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void onPackageChanged(String packageName) { 4685bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_DIRECTORIES, packageName); 4686d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4687d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4688619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 468943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * Finds all distinct account types and data sets present in the specified table. 4690627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov */ 469143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro private Set<AccountWithDataSet> findValidAccountsWithDataSets(String table) { 469243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Set<AccountWithDataSet> accountsWithDataSets = new HashSet<AccountWithDataSet>(); 46935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().rawQuery( 469443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro "SELECT DISTINCT " + RawContacts.ACCOUNT_NAME + "," + RawContacts.ACCOUNT_TYPE + 469543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro "," + RawContacts.DATA_SET + 469643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " FROM " + table, null); 4697627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 4698627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov while (c.moveToNext()) { 4699dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!c.isNull(0) || !c.isNull(1)) { 470043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountsWithDataSets.add( 470143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new AccountWithDataSet(c.getString(0), c.getString(1), c.getString(2))); 4702627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4703627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4704627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } finally { 4705627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c.close(); 4706627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 470743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro return accountsWithDataSets; 4708627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4709627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 47104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 47114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 47124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 471315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 471415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mReadAccessLatch); 471515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 47165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Query the profile DB if appropriate. 47175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 47185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 47195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileProvider.query(uri, projection, selection, selectionArgs, sortOrder); 47205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 47215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 47225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Otherwise proceed with a normal query against the contacts DB. 47235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 47245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mContactsHelper.getReadableDatabase()); 4725d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String directory = getQueryParameter(uri, ContactsContract.DIRECTORY_PARAM_KEY); 4726385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov if (directory == null) { 4727b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return addSnippetExtrasToCursor(uri, 47285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, -1)); 4729385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } else if (directory.equals("0")) { 4730b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return addSnippetExtrasToCursor(uri, 47313716f1447ceb21180d1301790eabd8b9453f486dDave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, 47325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Directory.DEFAULT)); 4733d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } else if (directory.equals("1")) { 4734b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return addSnippetExtrasToCursor(uri, 47353716f1447ceb21180d1301790eabd8b9453f486dDave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, 47365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Directory.LOCAL_INVISIBLE)); 4737d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4738d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4739d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov DirectoryInfo directoryInfo = getDirectoryAuthority(directory); 4740d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo == null) { 4741a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov Log.e(TAG, "Invalid directory ID: " + uri); 4742a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov return null; 4743d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4744d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4745d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Builder builder = new Uri.Builder(); 4746d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.scheme(ContentResolver.SCHEME_CONTENT); 4747d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.authority(directoryInfo.authority); 4748d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.encodedPath(uri.getEncodedPath()); 4749d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountName != null) { 4750d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, directoryInfo.accountName); 4751d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4752d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountType != null) { 4753d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, directoryInfo.accountType); 4754d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 47552e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 47562e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov String limit = getLimit(uri); 47572e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov if (limit != null) { 47582e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov builder.appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, limit); 47592e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov } 47602e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 4761d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Uri directoryUri = builder.build(); 476209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 476309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov if (projection == null) { 476409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov projection = getDefaultProjection(uri); 476509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 476609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 4767332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov Cursor cursor = getContext().getContentResolver().query(directoryUri, projection, selection, 4768d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov selectionArgs, sortOrder); 47696ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 47706ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (cursor == null) { 47716ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return null; 47726ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 47736ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 4774547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro CrossProcessCursor crossProcessCursor = getCrossProcessCursor(cursor); 4775547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro if (crossProcessCursor != null) { 4776b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return addSnippetExtrasToCursor(uri, cursor); 4777547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } else { 4778b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return matrixCursorFromCursor(addSnippetExtrasToCursor(uri, cursor)); 4779547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } 47803716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 47813716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 4782b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private Cursor addSnippetExtrasToCursor(Uri uri, Cursor cursor) { 4783547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro 4784547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro // If the cursor doesn't contain a snippet column, don't bother wrapping it. 4785547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro if (cursor.getColumnIndex(SearchSnippetColumns.SNIPPET) < 0) { 4786b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return cursor; 4787547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } 4788547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro 47893716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Parse out snippet arguments for use when snippets are retrieved from the cursor. 47903716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String[] args = null; 47913716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String snippetArgs = 47923716f1447ceb21180d1301790eabd8b9453f486dDave Santoro getQueryParameter(uri, SearchSnippetColumns.SNIPPET_ARGS_PARAM_KEY); 47933716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (snippetArgs != null) { 47943716f1447ceb21180d1301790eabd8b9453f486dDave Santoro args = snippetArgs.split(","); 47953716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 47963716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 47973716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String query = uri.getLastPathSegment(); 47983716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String startMatch = args != null && args.length > 0 ? args[0] 47993716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_START_MATCH; 48003716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String endMatch = args != null && args.length > 1 ? args[1] 48013716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_END_MATCH; 48023716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String ellipsis = args != null && args.length > 2 ? args[2] 48033716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_ELLIPSIS; 48043716f1447ceb21180d1301790eabd8b9453f486dDave Santoro int maxTokens = args != null && args.length > 3 ? Integer.parseInt(args[3]) 48053716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_MAX_TOKENS; 48063716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 4807b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson // Snippet data is needed for the snippeting on the client side, so store it in the cursor 4808b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (cursor instanceof AbstractCursor && deferredSnippetingRequested(uri)){ 4809b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson Bundle oldExtras = cursor.getExtras(); 4810b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson Bundle extras = new Bundle(); 4811b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (oldExtras != null) { 4812b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson extras.putAll(oldExtras); 4813b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 4814b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson extras.putString(ContactsContract.DEFERRED_SNIPPETING_QUERY, query); 4815b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 4816b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson ((AbstractCursor) cursor).setExtras(extras); 48175517770250b3afa4fd88b6869c3244680821d222Dave Santoro } 4818b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return cursor; 4819b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 4820b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 4821b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private Cursor addDeferredSnippetingExtra(Cursor cursor) { 4822b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (cursor instanceof AbstractCursor){ 4823b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson Bundle oldExtras = cursor.getExtras(); 4824b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson Bundle extras = new Bundle(); 4825b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (oldExtras != null) { 4826b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson extras.putAll(oldExtras); 4827b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 4828b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson extras.putBoolean(ContactsContract.DEFERRED_SNIPPETING, true); 4829b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson ((AbstractCursor) cursor).setExtras(extras); 4830b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 4831b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return cursor; 48326ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 48336ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 48346ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov private CrossProcessCursor getCrossProcessCursor(Cursor cursor) { 48356ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov Cursor c = cursor; 48366ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (c instanceof CrossProcessCursor) { 48376ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return (CrossProcessCursor) c; 48386ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } else if (c instanceof CursorWindow) { 48396ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return getCrossProcessCursor(((CursorWrapper) c).getWrappedCursor()); 48406ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } else { 48416ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return null; 48426ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 48436ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 48446ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 48456ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov public MatrixCursor matrixCursorFromCursor(Cursor cursor) { 48466ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames()); 48476ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov int numColumns = cursor.getColumnCount(); 48486ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov String data[] = new String[numColumns]; 48496ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov cursor.moveToPosition(-1); 48506ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov while (cursor.moveToNext()) { 48516ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov for (int i = 0; i < numColumns; i++) { 48526ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov data[i] = cursor.getString(i); 48536ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 48546ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov newCursor.addRow(data); 4855332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov } 48566ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return newCursor; 4857d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4858d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4859d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final class DirectoryQuery { 4860d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 4861d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory._ID, 4862d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.DIRECTORY_AUTHORITY, 4863d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_NAME, 4864d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_TYPE 4865d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov }; 4866d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4867d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int DIRECTORY_ID = 0; 4868d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int AUTHORITY = 1; 4869d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_NAME = 2; 4870d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_TYPE = 3; 4871d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4872d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4873d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 4874d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Reads and caches directory information for the database. 4875d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 4876d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private DirectoryInfo getDirectoryAuthority(String directoryId) { 48774458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov synchronized (mDirectoryCache) { 48784458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov if (!mDirectoryCacheValid) { 48794458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCache.clear(); 48805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mDbHelper.get().getReadableDatabase(); 488149d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov Cursor cursor = db.query(Tables.DIRECTORIES, 48824458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DirectoryQuery.COLUMNS, 48834458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov null, null, null, null, null); 48844458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov try { 48854458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov while (cursor.moveToNext()) { 48864458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DirectoryInfo info = new DirectoryInfo(); 48874458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov String id = cursor.getString(DirectoryQuery.DIRECTORY_ID); 48884458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.authority = cursor.getString(DirectoryQuery.AUTHORITY); 48894458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.accountName = cursor.getString(DirectoryQuery.ACCOUNT_NAME); 48904458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.accountType = cursor.getString(DirectoryQuery.ACCOUNT_TYPE); 48914458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCache.put(id, info); 48924458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 48934458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } finally { 48944458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov cursor.close(); 4895d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 48964458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCacheValid = true; 4897d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4898d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 48994458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov return mDirectoryCache.get(directoryId); 49004458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 4901d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4902d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 490372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void resetDirectoryCache() { 49044458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov synchronized(mDirectoryCache) { 49054458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCacheValid = false; 49064458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 490772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 490872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 49095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro protected Cursor queryLocal(Uri uri, String[] projection, String selection, 49105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String[] selectionArgs, String sortOrder, long directoryId) { 4911bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 4912bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 4913bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 49140b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 49155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 49165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 49175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 49185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 491935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4920d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 49211f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 4922c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 4923b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson boolean snippetDeferred = false; 4924c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 49252ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // The expression used in bundleLetterCountExtras() to get count. 49262ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki String addressBookIndexerCountExpression = null; 49272ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 4928a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 49294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 493035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 49315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 49325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().query(mActiveDb.get(), projection, selection, 49335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs, sortOrder); 493435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4935d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 4936763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 49374b64b6e8f448938434cb1e022a4e7dfaae8f9c8cMakoto Onuki appendLocalDirectorySelectionIfNeeded(qb, directoryId); 4938619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 4939619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4940619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4941d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 49424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 4943763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 49444da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 49454da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 49466bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 49476bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 49486bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 49495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 49505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 49515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 49525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 49535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 49545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 4955fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 49565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 4957a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 49585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 49595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 49605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 49615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 4962763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 4963a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 49645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 4965a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 4966a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey); 4967a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 49685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 49695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4972763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 49734da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 49745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String.valueOf(lookupContactIdByLookupKey(mActiveDb.get(), lookupKey))); 49754da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 49765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 49775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49792149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov case CONTACTS_LOOKUP_DATA: 49802149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov case CONTACTS_LOOKUP_ID_DATA: { 49812149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 49822149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov int segmentCount = pathSegments.size(); 49832149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount < 4) { 49845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 49852149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov "Missing a lookup key", uri)); 49862149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 49872149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov String lookupKey = pathSegments.get(2); 49882149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount == 5) { 49892149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 49902149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 49912149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(lookupQb, uri, projection, false); 4992a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 49935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 4994a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 4995a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.CONTACT_ID, contactId, Data.LOOKUP_KEY, lookupKey); 4996a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 49972149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov return c; 49982149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 49992149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 50002149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov // TODO see if the contact exists but has no data rows (rare) 50012149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 50022149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 50032149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 50045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 50052149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 500624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro String.valueOf(contactId)); 50072149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov qb.appendWhere(" AND " + Data.CONTACT_ID + "=?"); 50082149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov break; 50092149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 50102149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 50113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_ID_STREAM_ITEMS: { 50123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long contactId = Long.parseLong(uri.getPathSegments().get(1)); 50133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 50143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 5015af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann qb.appendWhere(StreamItems.CONTACT_ID + "=?"); 50163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 50173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 50183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 50193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_LOOKUP_STREAM_ITEMS: 50203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_LOOKUP_ID_STREAM_ITEMS: { 50213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<String> pathSegments = uri.getPathSegments(); 50223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann int segmentCount = pathSegments.size(); 50233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (segmentCount < 4) { 50245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 50253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann "Missing a lookup key", uri)); 50263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 50273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String lookupKey = pathSegments.get(2); 50283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (segmentCount == 5) { 50293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long contactId = Long.parseLong(pathSegments.get(3)); 50303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 50313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(lookupQb); 50325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 50333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann projection, selection, selectionArgs, sortOrder, groupBy, limit, 5034af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann StreamItems.CONTACT_ID, contactId, 5035af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann StreamItems.CONTACT_LOOKUP_KEY, lookupKey); 50363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (c != null) { 50373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return c; 50383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 50393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 50403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 50413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 50425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 50433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 50443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(RawContacts.CONTACT_ID + "=?"); 50453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 50463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 50473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 5048f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 504942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 50505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 5051ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 5052f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 50534da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 505424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro String.valueOf(contactId)); 50554da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 5056f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 5057f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 5058f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 505942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 506042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); 506142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann String currentDateString = dateFormat.format(new Date()).toString(); 50625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().rawQuery( 506342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann "SELECT" + 506442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " 'vcards_' || ? || '.vcf' AS " + OpenableColumns.DISPLAY_NAME + "," + 506542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " NULL AS " + OpenableColumns.SIZE, 506642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann new String[] { currentDateString }); 506742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 506842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 5069ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 5070916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String filterParam = ""; 5071b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson boolean deferredSnipRequested = deferredSnippetingRequested(uri); 5072ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 5073916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov filterParam = uri.getLastPathSegment(); 5074ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 50757ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov setTablesAndProjectionMapForContactsWithSnippet( 5076b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson qb, uri, projection, filterParam, directoryId, 5077b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson deferredSnipRequested); 5078b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson snippetDeferred = isSingleWordQuery(filterParam) && 5079b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson deferredSnipRequested && snippetNeeded(projection); 5080ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5081ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5082ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 5083ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 5084ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 50852f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Basically the resultant SQL should look like this: 50862f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // (SQL for listing starred items) 50872f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // UNION ALL 50882f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // (SQL for listing frequently contacted items) 50892f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // ORDER BY ... 50902f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 50912f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final boolean phoneOnly = readBooleanQueryParameter( 50922f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa uri, ContactsContract.STREQUENT_PHONE_ONLY, false); 50932f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (match == CONTACTS_STREQUENT_FILTER && uri.getPathSegments().size() > 3) { 50944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 50954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5096e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 50975e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 50982f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa selection = DbQueryUtils.concatenateClauses(selection, sb.toString()); 50994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 51004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 51012f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa String[] subProjection = null; 51025e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 51032f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa subProjection = appendProjectionArg(projection, TIMES_USED_SORT_COLUMN); 51045e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 51055e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 51064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 51074928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, false); 51084928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setProjectionMap(phoneOnly ? 51094928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa sStrequentPhoneOnlyStarredProjectionMap 51104928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa : sStrequentStarredProjectionMap); 51119dbfd650ccf93714f3266e80f9fbdbcb526ae7b3Daisuke Miyakawa if (phoneOnly) { 51125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro qb.appendWhere(DbQueryUtils.concatenateClauses( 51135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection, Contacts.HAS_PHONE_NUMBER + "=1")); 51149dbfd650ccf93714f3266e80f9fbdbcb526ae7b3Daisuke Miyakawa } 51152f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.setStrict(true); 51162f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final String starredQuery = qb.buildQuery(subProjection, 511724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Contacts.STARRED + "=1", Contacts._ID, null, null, null); 5118d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 51192f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Reset the builder. 5120d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 51212f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.setStrict(true); 51224928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 51234928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // Build the second query for frequent part. 51244928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa final String frequentQuery; 51254928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa if (phoneOnly) { 51264928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa final StringBuilder tableBuilder = new StringBuilder(); 51274928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // In phone only mode, we need to look at view_data instead of 51284928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // contacts/raw_contacts to obtain actual phone numbers. One problem is that 51294928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // view_data is much larger than view_contacts, so our query might become much 51304928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // slower. 51314928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // 51324928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // To avoid the possible slow down, we start from data usage table and join 51334928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // view_data to the table, assuming data usage table is quite smaller than 51344928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // data rows (almost always it should be), and we don't want any phone 51354928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // numbers not used by the user. This way sqlite is able to drop a number of 51364928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // rows in view_data in the early stage of data lookup. 51374928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa tableBuilder.append(Tables.DATA_USAGE_STAT 51384928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + " INNER JOIN " + Views.DATA + " " + Tables.DATA 51394928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + " ON (" + DataUsageStatColumns.CONCRETE_DATA_ID + "=" 51404928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + DataColumns.CONCRETE_ID + " AND " 51414928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + DataUsageStatColumns.CONCRETE_USAGE_TYPE + "=" 51424928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + DataUsageStatColumns.USAGE_TYPE_INT_CALL + ")"); 51434928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa appendContactPresenceJoin(tableBuilder, projection, RawContacts.CONTACT_ID); 51444928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa appendContactStatusUpdateJoin(tableBuilder, projection, 51454928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa ContactsColumns.LAST_STATUS_UPDATE_ID); 51464928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 51474928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setTables(tableBuilder.toString()); 51484928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setProjectionMap(sStrequentPhoneOnlyFrequentProjectionMap); 51494928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.appendWhere(DbQueryUtils.concatenateClauses( 51504928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa selection, 51514928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa Contacts.STARRED + "=0 OR " + Contacts.STARRED + " IS NULL", 51524928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa MimetypesColumns.MIMETYPE + " IN (" 51534928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + "'" + Phone.CONTENT_ITEM_TYPE + "', " 51544928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + "'" + SipAddress.CONTENT_ITEM_TYPE + "')")); 51554928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa frequentQuery = qb.buildQuery(subProjection, null, null, null, null, null); 51564928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa } else { 51574928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, true); 51584928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setProjectionMap(sStrequentFrequentProjectionMap); 51594928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.appendWhere(DbQueryUtils.concatenateClauses( 51604928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa selection, 51615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro "(" + Contacts.STARRED + " =0 OR " + Contacts.STARRED + " IS NULL)")); 51624928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa frequentQuery = qb.buildQuery(subProjection, 51634928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa null, Contacts._ID, null, null, null); 51644928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa } 5165d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 5166d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 51672f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final String unionQuery = 51682f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 51692f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa STREQUENT_ORDER_BY, STREQUENT_LIMIT); 51702f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 51712f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Here, we need to use selection / selectionArgs (supplied from users) "twice", 51722f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // as we want them both for starred items and for frequently contacted items. 51732f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // 51742f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // e.g. if the user specify selection = "starred =?" and selectionArgs = "0", 51752f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // the resultant SQL should be like: 51762f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // SELECT ... WHERE starred =? AND ... 51772f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // UNION ALL 51782f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // SELECT ... WHERE starred =? AND ... 51792f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa String[] doubledSelectionArgs = null; 51802f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (selectionArgs != null) { 51812f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final int length = selectionArgs.length; 51822f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa doubledSelectionArgs = new String[length * 2]; 51837d7d0e95636344c01eb4e4d034791c199bee98e9Daisuke Miyakawa System.arraycopy(selectionArgs, 0, doubledSelectionArgs, 0, length); 51847d7d0e95636344c01eb4e4d034791c199bee98e9Daisuke Miyakawa System.arraycopy(selectionArgs, 0, doubledSelectionArgs, length, length); 51852f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 51862f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 51875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().rawQuery(unionQuery, doubledSelectionArgs); 51882f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (cursor != null) { 51892f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa cursor.setNotificationUri(getContext().getContentResolver(), 5190d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 5191d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 51922f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa return cursor; 5193d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 5194d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 519545ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa case CONTACTS_FREQUENT: { 519645ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, true); 519745ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa qb.setProjectionMap(sStrequentFrequentProjectionMap); 519845ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa groupBy = Contacts._ID; 519945ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa if (!TextUtils.isEmpty(sortOrder)) { 520045ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa sortOrder = FREQUENT_ORDER_BY + ", " + sortOrder; 520145ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa } else { 520245ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa sortOrder = FREQUENT_ORDER_BY; 520345ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa } 520445ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa break; 520545ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa } 520645ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa 5207ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 5208763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 5209b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 521071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 52117cf50494501938f175d288077145acf49da8f171Daniel Lehmann String groupMimeTypeId = String.valueOf( 52127cf50494501938f175d288077145acf49da8f171Daniel Lehmann mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 52134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 52147cf50494501938f175d288077145acf49da8f171Daniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, groupMimeTypeId); 5215b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5216b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 5217b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5218b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 521924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: { 522024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForContacts(qb, uri, projection); 522124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 522224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 522324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 522424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_ENTITIES: { 522524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForEntities(qb, uri, projection); 522624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 522724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 522824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 522924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: { 5230ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 523124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.setProjectionMap(sContactsVCardProjectionMap); 523224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 523324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 523424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 5235a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_DATA: { 52364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 523782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 52384da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 52394da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 52406bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 52416bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 524200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 5243a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 52443653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 524582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 52464da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 52474da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 52483653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 52493653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 52503653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 52513653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 5252a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_ENTITIES: { 5253a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 5254a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 5255a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 5256a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 5257a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 5258a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5259a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5260a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ENTITIES: 5261a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ID_ENTITIES: { 5262a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 5263a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov int segmentCount = pathSegments.size(); 5264a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount < 4) { 52655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 5266a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov "Missing a lookup key", uri)); 5267a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5268a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lookupKey = pathSegments.get(2); 5269a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount == 5) { 5270a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 5271a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 5272a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(lookupQb, uri, projection); 5273a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 5274a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 52755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 5276a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 5277a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.CONTACT_ID, contactId, 5278a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.LOOKUP_KEY, lookupKey); 5279a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 5280a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 5281a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5282a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5283a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5284a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 5285a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 52865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String.valueOf(lookupContactIdByLookupKey(mActiveDb.get(), lookupKey))); 5287a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + Contacts.Entity.CONTACT_ID + "=?"); 5288a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 5289a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5290a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 52913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 52923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 52933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 52943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 52953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 52963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 52973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 52983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 52999b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann qb.appendWhere(StreamItems._ID + "=?"); 53003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 53013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 53033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_LIMIT: { 53046802030a777c0c3ba1dc029c534cca4784260632Dave Santoro MatrixCursor cursor = new MatrixCursor(new String[]{StreamItems.MAX_ITEMS}, 1); 53056802030a777c0c3ba1dc029c534cca4784260632Dave Santoro cursor.addRow(new Object[]{MAX_STREAM_ITEMS_PER_RAW_CONTACT}); 53063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return cursor; 53073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 53093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 53103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 53113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 53123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 53143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 53153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 53163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 53173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemId); 53183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=?"); 53193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 53203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 53223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 53233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 53243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 53253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 53263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemPhotoId); 53273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemId); 53283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=? AND " + 53293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=?"); 53303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 53313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 5333f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case PHOTO_DIMENSIONS: { 5334f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro MatrixCursor cursor = new MatrixCursor( 5335f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro new String[]{DisplayPhoto.DISPLAY_MAX_DIM, DisplayPhoto.THUMBNAIL_MAX_DIM}, 5336f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1); 5337f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro cursor.addRow(new Object[]{mMaxDisplayPhotoDim, mMaxThumbnailPhotoDim}); 5338f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return cursor; 5339f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 5340f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 53414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 534282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 53437cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + "=" + 53447cf50494501938f175d288077145acf49da8f171Daniel Lehmann mDbHelper.get().getMimeTypeIdForPhone()); 53452ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 53462ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // Dedupe phone numbers per contact. 5347cf55cbe8932f620484a3634d13ecc116c32fdc99Daisuke Miyakawa groupBy = RawContacts.CONTACT_ID + ", " + Data.DATA1; 53482ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 53492ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // In this case, because we dedupe phone numbers, the address book indexer needs 53502ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // to take it into account too. (Otherwise headers will appear in wrong positions.) 53512ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // So use count(distinct pair(CONTACT_ID, PHONE NUMBER)) instead of count(*). 53522ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // But because there's no such thing as pair() on sqlite, we use 53532ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // CONTACT_ID || ',' || PHONE NUMBER instead. 53542ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // This only slows down the query by 14% with 10,000 contacts. 53552ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki addressBookIndexerCountExpression = "DISTINCT " 53562ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki + RawContacts.CONTACT_ID + "||','||" + Data.DATA1; 53572815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 53582815f58f72f109790585931f601a63ddc02536a5Evan Millar } 53592815f58f72f109790585931f601a63ddc02536a5Evan Millar 536048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 536182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 53624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 53637cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 53647cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForPhone()); 53654da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 536648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 536748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 536848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 5369ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 537046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String typeParam = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 537146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Integer typeInt = sDataUsageTypeMap.get(typeParam); 537246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (typeInt == null) { 537346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa typeInt = DataUsageStatColumns.USAGE_TYPE_INT_CALL; 537446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 537546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, true, typeInt); 53767cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 53777cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForPhone()); 5378ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 53794a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 53804a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5381a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 53825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 538345d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov boolean hasCondition = false; 53845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 53855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 53865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 5387155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN " + 5388155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov "(SELECT " + RawContactsColumns.CONCRETE_ID + 5389155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.SEARCH_INDEX + 5390155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 5391155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " ON (" + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID 5392155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov + "=" + RawContactsColumns.CONCRETE_CONTACT_ID + ")" + 5393155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " WHERE " + SearchIndexColumns.NAME + " MATCH "); 53942352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, sanitizeMatch(filterParam) + "*"); 5395155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(")"); 53965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 539745d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 53985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 53995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 5400892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String number = PhoneNumberUtils.normalizeNumber(filterParam); 5401892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (!TextUtils.isEmpty(number)) { 54025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 54035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 54045e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 5406892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov " IN (SELECT DISTINCT " + PhoneLookupColumns.DATA_ID 5407892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 5408892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 5409892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append(number); 5410892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append("%')"); 541145d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 541245d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov } 541345d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov 541445d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov if (!hasCondition) { 541545d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // If it is neither a phone number nor a name, the query should return 541645d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // an empty cursor. Let's ensure that. 541745d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov sb.append("0"); 54185e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54195e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 5420a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 5421ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 542258567abca253f1efa2db5c39e17e42dca589e916Daisuke Miyakawa groupBy = "(CASE WHEN " + PhoneColumns.NORMALIZED_NUMBER 542358567abca253f1efa2db5c39e17e42dca589e916Daisuke Miyakawa + " IS NOT NULL THEN " + PhoneColumns.NORMALIZED_NUMBER 542458567abca253f1efa2db5c39e17e42dca589e916Daisuke Miyakawa + " ELSE " + Phone.NUMBER + " END), " + RawContacts.CONTACT_ID; 5425a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 542646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String accountPromotionSortOrder = getAccountPromotionSortOrder(uri); 542746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(accountPromotionSortOrder)) { 542846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = accountPromotionSortOrder + ", " + PHONE_FILTER_SORT_ORDER; 542946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 543046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = PHONE_FILTER_SORT_ORDER; 543146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 5432a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 5433ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5434ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5435ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 54364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 543782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 54387cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 54397cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForEmail()); 54404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 54414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 54424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 544348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 544482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 54454da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 54467cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 54477cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForEmail() 54484da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + Data._ID + "=?"); 544948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 545048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 545148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 54525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 545382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 54547cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 54557cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForEmail()); 54564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 545708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String email = uri.getLastPathSegment(); 54585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String address = mDbHelper.get().extractAddressFromEmailAddress(email); 545908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, address); 546008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov qb.appendWhere(" AND UPPER(" + Email.DATA + ")=UPPER(?)"); 54614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 5462ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5463ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5464ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 54655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 546646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String typeParam = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 546746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Integer typeInt = sDataUsageTypeMap.get(typeParam); 546846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (typeInt == null) { 546946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa typeInt = DataUsageStatColumns.USAGE_TYPE_INT_LONG_TEXT; 547046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 547146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, true, typeInt); 547207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov String filterParam = null; 54737d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa 547407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 547507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = uri.getLastPathSegment(); 547607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (TextUtils.isEmpty(filterParam)) { 547707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = null; 547807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 547907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 54805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 548107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterParam == null) { 548207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // If the filter is unspecified, return nothing 548307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(" AND 0"); 548407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } else { 548507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 548607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append(" AND " + Data._ID + " IN ("); 548707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 548807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov "SELECT " + Data._ID + 548907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 54902a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "="); 54915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro sb.append(mDbHelper.get().getMimeTypeIdForEmail()); 54922a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov sb.append(" AND " + Data.DATA1 + " LIKE "); 549307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, filterParam + '%'); 549420938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 5495155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append( 5496155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " UNION SELECT " + Data._ID + 5497155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.DATA + 5498155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " WHERE +" + DataColumns.MIMETYPE_ID + "="); 54995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro sb.append(mDbHelper.get().getMimeTypeIdForEmail()); 5500155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(" AND " + Data.RAW_CONTACT_ID + " IN " + 5501155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov "(SELECT " + RawContactsColumns.CONCRETE_ID + 5502155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.SEARCH_INDEX + 5503155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 5504155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " ON (" + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID 5505155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov + "=" + RawContactsColumns.CONCRETE_CONTACT_ID + ")" + 5506155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " WHERE " + SearchIndexColumns.NAME + " MATCH "); 55072352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, sanitizeMatch(filterParam) + "*"); 5508155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(")"); 55095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 5511a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 55125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 5514a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 551546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String accountPromotionSortOrder = getAccountPromotionSortOrder(uri); 551646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(accountPromotionSortOrder)) { 551746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = accountPromotionSortOrder + ", " + EMAIL_FILTER_SORT_ORDER; 55187d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa } else { 55197d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa sortOrder = EMAIL_FILTER_SORT_ORDER; 55207d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa } 5521a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 55225e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 55235e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 5525ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 552682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 55277cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 55287cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForStructuredPostal()); 5529ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5530ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5531ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 553248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 553382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 55344da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 55357cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 55367cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForStructuredPostal()); 55374da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 553848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 553948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 554048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 5541d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS: 5542d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS: { 5543763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 55444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 55454f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 55464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 5547d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_ID: 5548d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID: { 55495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 5550763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 55514da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 55524da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 55534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 55544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 55554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 5556d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_DATA: 5557d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID_DATA: { 5558d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro int segment = match == RAW_CONTACTS_DATA ? 1 : 2; 5559d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(segment)); 556082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 55614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 55624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 556324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 556424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 556524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 55663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case RAW_CONTACTS_ID_STREAM_ITEMS: { 55673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 55683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 55693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 55703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItems.RAW_CONTACT_ID + "=?"); 55713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 55723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 557324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 557482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro case RAW_CONTACTS_ID_STREAM_ITEMS_ID: { 557582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 557682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro long streamItemId = Long.parseLong(uri.getPathSegments().get(3)); 557782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro setTablesAndProjectionMapForStreamItems(qb); 557882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(streamItemId)); 5579c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 558082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro qb.appendWhere(StreamItems.RAW_CONTACT_ID + "=? AND " + 558182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems._ID + "=?"); 558282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro break; 558382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 558482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 558524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID_ENTITIES: { 558624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(2)); 558724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 558824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForRawEntities(qb, uri); 55895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro qb.appendWhere(" AND " + RawContacts._ID + "=?"); 5590e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 5591e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 5592e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 5593d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case DATA: 5594d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_DATA: { 559582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 5596e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 5597e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 5598e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 5599d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case DATA_ID: 5600d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_DATA_ID: { 560182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 56024da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 56034da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 5604a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 5605a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 5606a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 5607a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 56084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5609a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 5610a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 5611a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 5612892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sortOrder = " length(lookup.normalized_number) DESC"; 5613a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 5614a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 5615e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 5616e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov String numberE164 = PhoneNumberUtils.formatNumberToE164(number, 56175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getCurrentCountryIso()); 5618892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String normalizedNumber = 5619892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov PhoneNumberUtils.normalizeNumber(number); 56205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().buildPhoneLookupAndContactQuery(qb, normalizedNumber, numberE164); 5621e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 5622e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 5623e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 5624e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 5625a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 5626a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 5627a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 5628ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 5629ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.GROUPS); 5630ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 5631f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 5632ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 5633ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 5634ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5635ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 5636ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.GROUPS); 5637ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 56384da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 56394da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Groups._ID + "=?"); 5640ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 5641ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 5642ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5643ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 5644f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa final boolean returnGroupCountPerAccount = 5645f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa readBooleanQueryParameter(uri, Groups.PARAM_RETURN_GROUP_COUNT_PER_ACCOUNT, 5646f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa false); 5647f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa qb.setTables(Views.GROUPS + " AS " + Tables.GROUPS); 5648f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa qb.setProjectionMap(returnGroupCountPerAccount ? 5649f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa sGroupsSummaryProjectionMapWithGroupCountPerAccount 5650f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa : sGroupsSummaryProjectionMap); 5651f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 5652f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa groupBy = GroupsColumns.CONCRETE_ID; 5653ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 5654ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 5655ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5656b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 56570c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 5658b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 5659b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 5660b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 5661b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 566231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 5663d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 56642d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 56652d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 56662d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 56672d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 566831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 5669d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 5670d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 567131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 567231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 567331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 567431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 56755b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ArrayList<AggregationSuggestionParameter> parameters = null; 56765b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov List<String> query = uri.getQueryParameters("query"); 56775b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov if (query != null && !query.isEmpty()) { 56785b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters = new ArrayList<AggregationSuggestionParameter>(query.size()); 56795b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov for (String parameter : query) { 56805b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov int offset = parameter.indexOf(':'); 56815b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters.add(offset == -1 56825b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ? new AggregationSuggestionParameter( 568376dfa406e2cde19c824983c37fc92c1c5bf63eecDaniel Lehmann AggregationSuggestions.PARAMETER_MATCH_NAME, 56845b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter) 56855b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov : new AggregationSuggestionParameter( 56865b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(0, offset), 56875b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(offset + 1))); 56885b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 56895b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 56905b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 5691763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 56927581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 56935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mAggregator.get().queryAggregationSuggestions(qb, projection, contactId, 56945b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov maxSuggestions, filter, parameters); 569531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 569631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 5697eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 5698eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 5699eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 5700f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 5701e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 5702e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 5703e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 57045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final String groupMembershipMimetypeId = Long.toString(mDbHelper.get() 5705e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 570682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 57075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().isInProjection(projection, Settings.UNGROUPED_COUNT)) { 5708e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 5709e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 571082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 57115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().isInProjection( 57125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro projection, Settings.UNGROUPED_WITH_PHONES)) { 5713e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 5714e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 5715e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 5716eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 5717eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 5718eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 57195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 57205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 57210a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 57225ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 57235ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 57245ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 572582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 57260a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 57274da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 57284da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=?"); 57295ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 57305ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 57315ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 5732c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 5733174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery( 57345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get(), uri, projection, limit); 5735c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5736c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 5737c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 57382d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill String lookupKey = uri.getLastPathSegment(); 5739174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String filter = getQueryParameter( 5740174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov uri, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA); 5741174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return mGlobalSearchSupport.handleSearchShortcutRefresh( 57425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get(), projection, lookupKey, filter); 5743c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5744c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 57451b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 5746ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 57471b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 57481b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 57491b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 57501b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 5751ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 57521b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 57531b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 57541b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 57551b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 57561b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 5757ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 57581b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 57591b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 57601b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 57611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 57621b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 5763ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 57641b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 576571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 57667cf50494501938f175d288077145acf49da8f171Daniel Lehmann String groupMimeTypeId = String.valueOf( 57677cf50494501938f175d288077145acf49da8f171Daniel Lehmann mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 57681b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 57697cf50494501938f175d288077145acf49da8f171Daniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, groupMimeTypeId); 57701b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 57711b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 57723202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro case RAW_CONTACT_ENTITIES: 57733202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro case PROFILE_RAW_CONTACT_ENTITIES: { 5774a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 577546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 577646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 577746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 577846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 577946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 5780a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 57814da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 57824da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 578346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 578446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 578546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 578609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov case PROVIDER_STATUS: { 578709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return queryProviderStatus(uri, projection); 578809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 578909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 5790d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES : { 5791d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 5792d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 5793d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 5794d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 5795d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 5796d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID : { 5797385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov long id = ContentUris.parseId(uri); 5798d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 5799d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 5800385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(id)); 5801d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.appendWhere(Directory._ID + "=?"); 5802d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 5803d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 5804d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 58057a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov case COMPLETE_NAME: { 58067a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return completeName(uri, projection); 58077a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 58087a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 58094f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 5810f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 5811c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 58124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 58134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 581409e69522745551522c55dff27424496f255def46Daniel Lehmann qb.setStrict(true); 58157f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov 5816ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov Cursor cursor = 58175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro query(mActiveDb.get(), qb, projection, selection, selectionArgs, sortOrder, groupBy, 58185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro limit); 5819ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (readBooleanQueryParameter(uri, ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, false)) { 58205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro cursor = bundleLetterCountExtras(cursor, mActiveDb.get(), qb, selection, 58212ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki selectionArgs, sortOrder, addressBookIndexerCountExpression); 5822ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5823b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (snippetDeferred) { 5824b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson cursor = addDeferredSnippetingExtra(cursor); 5825b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 5826ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return cursor; 58275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 58285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 58295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 58305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 58315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 5832038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 5833038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 5834038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 5835038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 58365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 58375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 58384f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 58394f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 58404f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 58414f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 58424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 58434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 584409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov /** 584509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov * Creates a single-row cursor containing the current status of the provider. 584609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov */ 584709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private Cursor queryProviderStatus(Uri uri, String[] projection) { 584809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 584909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov RowBuilder row = cursor.newRow(); 585009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov for (int i = 0; i < projection.length; i++) { 585109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov if (ProviderStatus.STATUS.equals(projection[i])) { 585209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mProviderStatus); 585309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } else if (ProviderStatus.DATA1.equals(projection[i])) { 585409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mEstimatedStorageRequirement); 585509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 585609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 585709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return cursor; 585809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 585909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 5860a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** 5861a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * Runs the query with the supplied contact ID and lookup ID. If the query succeeds, 5862a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * it returns the resulting cursor, otherwise it returns null and the calling 5863a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * method needs to resolve the lookup key and rerun the query. 5864a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov */ 5865a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private Cursor queryWithContactIdAndLookupKey(SQLiteQueryBuilder lookupQb, 5866a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteDatabase db, Uri uri, 5867a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection, String selection, String[] selectionArgs, 5868a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String sortOrder, String groupBy, String limit, 5869a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn, long contactId, String lookupKeyColumn, String lookupKey) { 5870a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] args; 5871a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (selectionArgs == null) { 5872a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[2]; 5873a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } else { 5874a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[selectionArgs.length + 2]; 5875a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 5876a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5877a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[0] = String.valueOf(contactId); 5878a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[1] = Uri.encode(lookupKey); 5879a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(contactIdColumn + "=? AND " + lookupKeyColumn + "=?"); 5880a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, args, sortOrder, 5881a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov groupBy, limit); 5882a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c.getCount() != 0) { 5883a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 5884a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5885a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5886a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov c.close(); 5887a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return null; 5888a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 588909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 5890bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov private static final class AddressBookIndexQuery { 5891bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String LETTER = "letter"; 5892bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String TITLE = "title"; 5893bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String COUNT = "count"; 5894ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5895bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String[] COLUMNS = new String[] { 5896bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov LETTER, TITLE, COUNT 5897ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 5898ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5899bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_LETTER = 0; 5900bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_TITLE = 1; 5901bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_COUNT = 2; 5902bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 59035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // The first letter of the sort key column is what is used for the index headings. 59045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public static final String SECTION_HEADING = "SUBSTR(%1$s,1,1)"; 590524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 5906de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa public static final String ORDER_BY = LETTER + " COLLATE " + PHONEBOOK_COLLATOR_NAME; 5907ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5908ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5909ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov /** 5910ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * Computes counts by the address book index titles and adds the resulting tally 5911ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * to the returned cursor as a bundle of extras. 5912ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov */ 5913ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov private Cursor bundleLetterCountExtras(Cursor cursor, final SQLiteDatabase db, 59142ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki SQLiteQueryBuilder qb, String selection, String[] selectionArgs, String sortOrder, 59152ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki String countExpression) { 5916409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki if (!(cursor instanceof AbstractCursor)) { 5917409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki Log.w(TAG, "Unable to bundle extras. Cursor is not AbstractCursor."); 5918409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki return cursor; 5919409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki } 5920ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortKey; 5921ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5922ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // The sort order suffix could be something like "DESC". 5923ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // We want to preserve it in the query even though we will change 5924ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // the sort column itself. 5925ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortOrderSuffix = ""; 5926ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (sortOrder != null) { 5927ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int spaceIndex = sortOrder.indexOf(' '); 5928ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (spaceIndex != -1) { 5929ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder.substring(0, spaceIndex); 5930ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortOrderSuffix = sortOrder.substring(spaceIndex); 5931ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 5932ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder; 5933ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5934ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 5935ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = Contacts.SORT_KEY_PRIMARY; 5936ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5937ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5938bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String locale = getLocale().toString(); 5939ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov HashMap<String, String> projectionMap = Maps.newHashMap(); 59405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String sectionHeading = String.format(AddressBookIndexQuery.SECTION_HEADING, sortKey); 5941bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov projectionMap.put(AddressBookIndexQuery.LETTER, 594224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro sectionHeading + " AS " + AddressBookIndexQuery.LETTER); 5943bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 59442ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // If "what to count" is not specified, we just count all records. 59452ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki if (TextUtils.isEmpty(countExpression)) { 59462ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki countExpression = "*"; 59472ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki } 59482ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 5949bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov /** 5950bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * Use the GET_PHONEBOOK_INDEX function, which is an android extension for SQLite3, 5951bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * to map the first letter of the sort key to a character that is traditionally 5952bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * used in phonebooks to represent that letter. For example, in Korean it will 5953bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * be the first consonant in the letter; for Japanese it will be Hiragana rather 5954bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * than Katakana. 5955bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov */ 5956ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.TITLE, 595724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro "GET_PHONEBOOK_INDEX(" + sectionHeading + ",'" + locale + "')" 5958bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov + " AS " + AddressBookIndexQuery.TITLE); 5959ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.COUNT, 59602ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki "COUNT(" + countExpression + ") AS " + AddressBookIndexQuery.COUNT); 5961ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov qb.setProjectionMap(projectionMap); 5962ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5963f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov Cursor indexCursor = qb.query(db, AddressBookIndexQuery.COLUMNS, selection, selectionArgs, 5964ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY, null /* having */, 5965ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY + sortOrderSuffix); 5966ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5967ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov try { 5968f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov int groupCount = indexCursor.getCount(); 5969ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String titles[] = new String[groupCount]; 5970ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int counts[] = new int[groupCount]; 5971bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int indexCount = 0; 5972bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String currentTitle = null; 5973bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 5974bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // Since GET_PHONEBOOK_INDEX is a many-to-1 function, we may end up 5975bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // with multiple entries for the same title. The following code 5976bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // collapses those duplicates. 5977ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov for (int i = 0; i < groupCount; i++) { 5978f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.moveToNext(); 5979bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String title = indexCursor.getString(AddressBookIndexQuery.COLUMN_TITLE); 5980bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int count = indexCursor.getInt(AddressBookIndexQuery.COLUMN_COUNT); 5981bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount == 0 || !TextUtils.equals(title, currentTitle)) { 5982bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles[indexCount] = currentTitle = title; 5983bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount] = count; 5984bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov indexCount++; 5985bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } else { 5986bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount - 1] += count; 5987bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 5988bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 5989bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 5990bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount < groupCount) { 5991bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String[] newTitles = new String[indexCount]; 5992bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(titles, 0, newTitles, 0, indexCount); 5993bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles = newTitles; 5994bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 5995bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int[] newCounts = new int[indexCount]; 5996bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(counts, 0, newCounts, 0, indexCount); 5997bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts = newCounts; 5998ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5999ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 6000409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki final Bundle bundle = new Bundle(); 6001409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki bundle.putStringArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, titles); 6002409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki bundle.putIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS, counts); 6003409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki 6004409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki ((AbstractCursor) cursor).setExtras(bundle); 6005409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki return cursor; 6006ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } finally { 6007f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.close(); 6008ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 6009ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 6010ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 60112d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill /** 601292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Returns the contact Id for the contact identified by the lookupKey. 601392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Robust against changes in the lookup key: if the key has changed, will 601492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * look up the contact by the raw contact IDs or name encoded in the lookup 601592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * key. 60162d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill */ 60172d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill public long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 60185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 60195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 60205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 602192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov long contactId = -1; 60225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_PROFILE)) { 60235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // We should already be in a profile database context, so just look up a single contact. 60245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro contactId = lookupSingleContactId(db); 60255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 60265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 602792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_SOURCE_ID)) { 602892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdBySourceIds(db, segments); 602992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 603092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 603192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 603292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 603392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 603492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov boolean hasRawContactIds = 603592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID); 603692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds) { 603792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdByRawContactIds(db, segments); 603892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 603992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 604092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 604192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 604292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 604392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds 604492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME)) { 60455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 60465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 60495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private long lookupSingleContactId(SQLiteDatabase db) { 60525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = db.query(Tables.CONTACTS, new String[] {Contacts._ID}, 60535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro null, null, null, null, null, "1"); 60545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro try { 60555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (c.moveToFirst()) { 60565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return c.getLong(0); 60575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 60585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return -1; 60595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 60605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } finally { 60615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro c.close(); 60625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 60635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 60645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 60655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 606643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String TABLE = Views.RAW_CONTACTS; 60675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 60695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 607043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 60715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 60725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 60735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 60745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 607643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int ACCOUNT_TYPE_AND_DATA_SET = 1; 60775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 60785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 60795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 60825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 60835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 60845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 60855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 60865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 608792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID) { 60885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 60895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 60905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 60935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 60945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 60965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 60975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 60985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 609943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String accountTypeAndDataSet = 610043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE_AND_DATA_SET); 61015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 61025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 610343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ContactLookupKey.getAccountHashCode(accountTypeAndDataSet, accountName); 61045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 61055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 61065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 610792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID 610892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 61095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 61105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 61115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 61125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 61165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 61175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 61205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 612292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByRawContactIdQuery { 612343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String TABLE = Views.RAW_CONTACTS; 61245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 61265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 612743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 61285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 612992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts._ID, 61305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 61315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 613343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int ACCOUNT_TYPE_AND_DATA_SET = 1; 61345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 613592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ID = 3; 61365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 613892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByRawContactIds(SQLiteDatabase db, 613992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 614092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 614192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(RawContacts._ID + " IN ("); 61425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 61435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 614492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 614592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(segment.rawContactId); 614692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(","); 61475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 614992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 615092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 61515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 615292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Cursor c = db.query(LookupByRawContactIdQuery.TABLE, LookupByRawContactIdQuery.COLUMNS, 615392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.toString(), null, null, null, null); 615492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov try { 615592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov while (c.moveToNext()) { 615643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String accountTypeAndDataSet = c.getString( 615743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro LookupByRawContactIdQuery.ACCOUNT_TYPE_AND_DATA_SET); 615892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountName = c.getString(LookupByRawContactIdQuery.ACCOUNT_NAME); 615992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int accountHashCode = 616043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ContactLookupKey.getAccountHashCode(accountTypeAndDataSet, accountName); 616192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String rawContactId = c.getString(LookupByRawContactIdQuery.ID); 616292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 616392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 616492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID 616592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 616692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && segment.rawContactId.equals(rawContactId)) { 616792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov segment.contactId = c.getLong(LookupByRawContactIdQuery.CONTACT_ID); 616892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov break; 616992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 617092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 617192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 617292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } finally { 617392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov c.close(); 61745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 617692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return getMostReferencedContactId(segments); 617792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 617892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 617992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByDisplayNameQuery { 618092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 618192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 618292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String COLUMNS[] = { 618392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.CONTACT_ID, 618443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 618592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 618692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 618792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov }; 618892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 618992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int CONTACT_ID = 0; 619043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int ACCOUNT_TYPE_AND_DATA_SET = 1; 619192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_NAME = 2; 619292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int NORMALIZED_NAME = 3; 619392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 619492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 619592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 619692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 61975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 61985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 61995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 62005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 620192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 620292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 62035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 62045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 62055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 62085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 62095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 62105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 62125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 62135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 62145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 621543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String accountTypeAndDataSet = 621643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE_AND_DATA_SET); 62175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 62185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 621943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ContactLookupKey.getAccountHashCode(accountTypeAndDataSet, accountName); 62205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 62215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 62225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 622392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if ((segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 622492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) 622592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 62265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 62275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 62285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 62295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 62335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 62345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 62375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 623992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private boolean lookupKeyContainsType(ArrayList<LookupKeySegment> segments, int lookupType) { 624092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 624192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 624292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == lookupType) { 624392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return true; 624492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 624592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 624692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 624792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return false; 624892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 624992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 6250ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateLookupKeyForRawContact(SQLiteDatabase db, long rawContactId) { 62515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateLookupKeyForRawContact(db, rawContactId); 6252ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov } 6253ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov 62545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 62555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 62565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 62575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 62585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 62595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 62615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 62625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 62645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 62655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 62675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 62685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 62695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 62705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 62715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 62725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 62735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 62745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 62755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 62765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 62785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 62795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 62835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 62845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 62855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 62865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 6289763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 6290763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 62914928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, false); 62922f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 62932f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 62942f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa /** 62954928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * @param includeDataUsageStat true when the table should include DataUsageStat table. 62964928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * Note that this uses INNER JOIN instead of LEFT OUTER JOIN, so some of data in Contacts 62974928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * may be dropped. 62982f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa */ 62992f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 63004928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa String[] projection, boolean includeDataUsageStat) { 630182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 6302ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.CONTACTS); 63032f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 63042f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Just for frequently contacted contacts in Strequent Uri handling. 63054928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa if (includeDataUsageStat) { 63062f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa sb.append(" INNER JOIN " + 6307ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann Views.DATA_USAGE_STAT + " AS " + Tables.DATA_USAGE_STAT + 63082f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa " ON (" + 63092f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa DbQueryUtils.concatenateClauses( 63102f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa DataUsageStatColumns.CONCRETE_TIMES_USED + " > 0", 63114928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa RawContacts.CONTACT_ID + "=" + Views.CONTACTS + "." + Contacts._ID) + 63122f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa ")"); 63132f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 63142f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 63157ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts._ID); 63167ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 6317916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 6318916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 6319916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 6320916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 6321916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** 6322916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * Finds name lookup records matching the supplied filter, picks one arbitrary match per 6323916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * contact and joins that with other contacts tables. 6324916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov */ 6325916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void setTablesAndProjectionMapForContactsWithSnippet(SQLiteQueryBuilder qb, Uri uri, 6326b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson String[] projection, String filter, long directoryId, boolean deferredSnippeting) { 63277ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov 63287ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 6329ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.CONTACTS); 6330916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 633103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (filter != null) { 633203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov filter = filter.trim(); 633303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 633403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 633530cc766756461da8d53933f88ea01dd2272a90ebDmitri Plotnikov if (TextUtils.isEmpty(filter) || (directoryId != -1 && directoryId != Directory.DEFAULT)) { 633630cc766756461da8d53933f88ea01dd2272a90ebDmitri Plotnikov sb.append(" JOIN (SELECT NULL AS " + SearchSnippetColumns.SNIPPET + " WHERE 0)"); 63375e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } else { 6338b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson appendSearchIndexJoin(sb, uri, projection, filter, deferredSnippeting); 63395e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 63407ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts._ID); 63417ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 634203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov qb.setTables(sb.toString()); 634303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionWithSnippetMap); 634403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 6345916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 634603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private void appendSearchIndexJoin( 6347b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson StringBuilder sb, Uri uri, String[] projection, String filter, 6348b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson boolean deferredSnippeting) { 6349916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 6350b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (snippetNeeded(projection)) { 635103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String[] args = null; 635203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String snippetArgs = 635303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov getQueryParameter(uri, SearchSnippetColumns.SNIPPET_ARGS_PARAM_KEY); 635403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (snippetArgs != null) { 635503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov args = snippetArgs.split(","); 635603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 635703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 63585e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String startMatch = args != null && args.length > 0 ? args[0] 63595e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_START_MATCH; 63605e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String endMatch = args != null && args.length > 1 ? args[1] 63615e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_END_MATCH; 63625e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String ellipsis = args != null && args.length > 2 ? args[2] 63635e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_ELLIPSIS; 63645e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov int maxTokens = args != null && args.length > 3 ? Integer.parseInt(args[3]) 63655e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_MAX_TOKENS; 63665e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 6367174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov appendSearchIndexJoin( 6368b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson sb, filter, true, startMatch, endMatch, ellipsis, maxTokens, 6369b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson deferredSnippeting); 6370174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } else { 6371b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson appendSearchIndexJoin(sb, filter, false, null, null, null, 0, false); 6372174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 6373174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 6374174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 6375174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov public void appendSearchIndexJoin(StringBuilder sb, String filter, 6376174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean snippetNeeded, String startMatch, String endMatch, String ellipsis, 6377b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson int maxTokens, boolean deferredSnippeting) { 6378174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean isEmailAddress = false; 6379174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String emailAddress = null; 6380174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean isPhoneNumber = false; 6381174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String phoneNumber = null; 6382174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String numberE164 = null; 6383174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 63843716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // If the query consists of a single word, we can do snippetizing after-the-fact for a 63853716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // performance boost. 6386b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson boolean singleTokenSearch = isSingleWordQuery(filter); 63873716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 6388174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov if (filter.indexOf('@') != -1) { 63895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro emailAddress = mDbHelper.get().extractAddressFromEmailAddress(filter); 6390174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov isEmailAddress = !TextUtils.isEmpty(emailAddress); 6391174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } else { 6392174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov isPhoneNumber = isPhoneNumber(filter); 639304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (isPhoneNumber) { 639404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann phoneNumber = PhoneNumberUtils.normalizeNumber(filter); 639504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann numberE164 = PhoneNumberUtils.formatNumberToE164(phoneNumber, 63965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getCountryIso()); 639704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 6398174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 6399174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 6400174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov sb.append(" JOIN (SELECT " + SearchIndexColumns.CONTACT_ID + " AS snippet_contact_id"); 6401174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov if (snippetNeeded) { 64025e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(", "); 64035e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov if (isEmailAddress) { 64043d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append("ifnull("); 64055e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 640604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("||(SELECT MIN(" + Email.ADDRESS + ")"); 640704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" FROM " + Tables.DATA_JOIN_RAW_CONTACTS); 640804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" WHERE " + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 640904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + RawContacts.CONTACT_ID + " AND " + Email.ADDRESS + " LIKE "); 641004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann DatabaseUtils.appendEscapedSQLString(sb, filter + "%"); 641104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(")||"); 64123d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 64133d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append(","); 64143716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 6415b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson // Optimization for single-token search (do only if requested). 6416b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (singleTokenSearch && deferredSnippeting) { 64173716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 64183716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 64193716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 64203716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 64213d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append(")"); 64223d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov } else if (isPhoneNumber) { 64233d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append("ifnull("); 64243d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 642504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("||(SELECT MIN(" + Phone.NUMBER + ")"); 642604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" FROM " + 642704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann Tables.DATA_JOIN_RAW_CONTACTS + " JOIN " + Tables.PHONE_LOOKUP); 642804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" ON " + DataColumns.CONCRETE_ID); 642904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + Tables.PHONE_LOOKUP + "." + PhoneLookupColumns.DATA_ID); 643004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" WHERE " + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 643104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + RawContacts.CONTACT_ID); 643204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" AND " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 643304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(phoneNumber); 643404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("%'"); 643504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (!TextUtils.isEmpty(numberE164)) { 643604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" OR " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 643704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(numberE164); 643804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("%'"); 643904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 644004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(")||"); 64415e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 64425e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 64433716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 6444b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson // Optimization for single-token search (do only if requested). 6445b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (singleTokenSearch && deferredSnippeting) { 64463716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 64473716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 64483716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 64493716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 64505e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(")"); 645103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 645204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann final String normalizedFilter = NameNormalizer.normalize(filter); 645304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (!TextUtils.isEmpty(normalizedFilter)) { 6454b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson // Optimization for single-token search (do only if requested).. 6455b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (singleTokenSearch && deferredSnippeting) { 64563716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 64573716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 64583716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("(CASE WHEN EXISTS (SELECT 1 FROM "); 64593716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.RAW_CONTACTS + " AS rc INNER JOIN "); 64603716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.NAME_LOOKUP + " AS nl ON (rc." + RawContacts._ID); 64613716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("=nl." + NameLookupColumns.RAW_CONTACT_ID); 64623716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(") WHERE nl." + NameLookupColumns.NORMALIZED_NAME); 64633716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(" GLOB '" + normalizedFilter + "*' AND "); 64643716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("nl." + NameLookupColumns.NAME_TYPE + "="); 64653716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(NameLookupType.NAME_COLLATION_KEY + " AND "); 64663716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 64673716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("=rc." + RawContacts.CONTACT_ID); 64683716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(") THEN NULL ELSE "); 64693716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 64703716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(" END)"); 64713716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 647204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } else { 647304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("NULL"); 647404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 647503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 64765e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" AS " + SearchSnippetColumns.SNIPPET); 64775e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 647803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 64795e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" FROM " + Tables.SEARCH_INDEX); 64805e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" WHERE "); 64815e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(Tables.SEARCH_INDEX + " MATCH "); 64825e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov if (isEmailAddress) { 64832352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, "\"" + sanitizeMatch(filter) + "*\""); 64843d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov } else if (isPhoneNumber) { 64852352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, 648604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann "\"" + sanitizeMatch(filter) + "*\" OR \"" + phoneNumber + "*\"" 64872352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov + (numberE164 != null ? " OR \"" + numberE164 + "\"" : "")); 648803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 64892352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, sanitizeMatch(filter) + "*"); 64909c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov } 649103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(") ON (" + Contacts._ID + "=snippet_contact_id)"); 6492a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov } 6493a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov 64942352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov private String sanitizeMatch(String filter) { 64952352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov // TODO more robust preprocessing of match expressions 64962352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov return filter.replace('-', ' ').replace('\"', ' '); 64972352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov } 64982352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov 64995e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov private void appendSnippetFunction( 65005e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov StringBuilder sb, String startMatch, String endMatch, String ellipsis, int maxTokens) { 65015e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append("snippet(" + Tables.SEARCH_INDEX + ","); 65025e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 65035e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 65045e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 65055e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 65065e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, ellipsis); 65075e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 65085e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov // The index of the column used for the snippet, "content" 65095e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(",1,"); 65105e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(maxTokens); 65115e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(")"); 65125e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 65135e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 6514763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 6515763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 6516ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.RAW_CONTACTS); 6517763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 6518763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 6519f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 6520763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 6521763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 6522a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForRawEntities(SQLiteQueryBuilder qb, Uri uri) { 6523ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.RAW_ENTITIES); 6524a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sRawEntityProjectionMap); 6525f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 652646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 652746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 652882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 652982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 653046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, distinct, null); 653146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 653246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 653346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 653446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * @param usageType when non-null {@link Tables#DATA_USAGE_STAT} is joined with the specified 653546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * type. 653646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 653746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 653846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String[] projection, boolean distinct, Integer usageType) { 653982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 6540ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.DATA); 654182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 654282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 6543a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, RawContacts.CONTACT_ID); 6544a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 6545a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 6546a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 65473296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 654846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (usageType != null) { 654946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa appendDataUsageStatJoin(sb, usageType, DataColumns.CONCRETE_ID); 655046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 655146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 655282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 6553f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov 6554f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov boolean useDistinct = distinct 65555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro || !mDbHelper.get().isInProjection(projection, DISTINCT_DATA_PROHIBITING_COLUMNS); 6556f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov qb.setDistinct(useDistinct); 6557f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov qb.setProjectionMap(useDistinct ? sDistinctDataProjectionMap : sDataProjectionMap); 6558f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 6559ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 6560ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 65610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 65620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 65630a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 6564ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.DATA); 65650a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 6566a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 6567a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 65680a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 6569a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 6570a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 6571a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6572a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 65733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void setTablesAndProjectionMapForStreamItems(SQLiteQueryBuilder qb) { 65749b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann qb.setTables(Views.STREAM_ITEMS); 65753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.setProjectionMap(sStreamItemsProjectionMap); 65763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 65773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 65783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void setTablesAndProjectionMapForStreamItemPhotos(SQLiteQueryBuilder qb) { 65791dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro qb.setTables(Tables.PHOTO_FILES 65801dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + " JOIN " + Tables.STREAM_ITEM_PHOTOS + " ON (" 65811dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + StreamItemPhotosColumns.CONCRETE_PHOTO_FILE_ID + "=" 65821dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + PhotoFilesColumns.CONCRETE_ID 65831dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + ") JOIN " + Tables.STREAM_ITEMS + " ON (" 65841dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=" 65850bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + StreamItemsColumns.CONCRETE_ID + ")" 65860bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + " JOIN " + Tables.RAW_CONTACTS + " ON (" 65870bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + StreamItemsColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID 65880bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + ")"); 65893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.setProjectionMap(sStreamItemPhotosProjectionMap); 65903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 65913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 6592a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForEntities(SQLiteQueryBuilder qb, Uri uri, 6593a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection) { 6594a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 6595ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.ENTITIES); 6596a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" data"); 6597a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6598a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts.Entity.CONTACT_ID); 6599a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 6600a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, Contacts.Entity.DATA_ID); 6601a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, Contacts.Entity.DATA_ID); 6602a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6603a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 6604a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sEntityProjectionMap); 6605f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 6606a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6607a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6608a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactStatusUpdateJoin(StringBuilder sb, String[] projection, 6609a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lastStatusUpdateIdColumn) { 66105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, 6611a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS, 6612a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 6613a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 6614a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 6615a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 6616a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 6617a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.ALIAS + 6618a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + lastStatusUpdateIdColumn + "=" 6619a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 66200a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 6621a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 66220a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 6623a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataStatusUpdateJoin(StringBuilder sb, String[] projection, 6624a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 66255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, 66260a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 66270a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 66280a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 66290a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 66300a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 66310a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 6632a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 6633a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + dataIdColumn + ")"); 66340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 6635a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6636a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 663746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private void appendDataUsageStatJoin(StringBuilder sb, int usageType, String dataIdColumn) { 663846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" LEFT OUTER JOIN " + Tables.DATA_USAGE_STAT + 663946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa " ON (" + DataUsageStatColumns.CONCRETE_DATA_ID + "=" + dataIdColumn + 664046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa " AND " + DataUsageStatColumns.CONCRETE_USAGE_TYPE + "=" + usageType + ")"); 664146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 664246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 6643a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactPresenceJoin(StringBuilder sb, String[] projection, 6644a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn) { 66455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, 6646a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_PRESENCE, Contacts.CONTACT_CHAT_CAPABILITY)) { 6647a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 6648a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + contactIdColumn + " = " 6649a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + ")"); 6650a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6651a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6652a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6653a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataPresenceJoin(StringBuilder sb, String[] projection, 6654a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 66555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, Data.PRESENCE, Data.CHAT_CAPABILITY)) { 6656a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 6657a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdates.DATA_ID + "=" + dataIdColumn + ")"); 6658a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6659a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6660a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 666124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private boolean appendLocalDirectorySelectionIfNeeded(SQLiteQueryBuilder qb, long directoryId) { 6662385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov if (directoryId == Directory.DEFAULT) { 6663385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov qb.appendWhere(Contacts._ID + " IN " + Tables.DEFAULT_DIRECTORY); 666424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return true; 6665385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } else if (directoryId == Directory.LOCAL_INVISIBLE){ 6666385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov qb.appendWhere(Contacts._ID + " NOT IN " + Tables.DEFAULT_DIRECTORY); 666724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return true; 666824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 666924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return false; 667024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 667124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 6672f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 6673f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 6674f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 667543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro final String dataSet = getQueryParameter(uri, RawContacts.DATA_SET); 6676e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6677e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 6678e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 6679e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 66805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 6681fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 6682e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 6683e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6684e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 6685e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 6686e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 6687e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 668843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String toAppend = RawContacts.ACCOUNT_NAME + "=" 66894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 66904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 669143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + DatabaseUtils.sqlEscapeString(accountType); 6692f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (dataSet == null) { 6693f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro toAppend += " AND " + RawContacts.DATA_SET + " IS NULL"; 6694f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } else { 6695f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro toAppend += " AND " + RawContacts.DATA_SET + "=" + 6696f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro DatabaseUtils.sqlEscapeString(dataSet); 669743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 669843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro qb.appendWhere(toAppend); 66994a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 67004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 67014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 67024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 67034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 6704e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 6705f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 6706f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 670743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro final String dataSet = getQueryParameter(uri, RawContacts.DATA_SET); 6708e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6709e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 6710e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 6711e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 67125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 6713fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 6714e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 6715e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6716e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 6717e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 6718e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 6719e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 6720e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 6721e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 6722e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 6723e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 6724f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (dataSet == null) { 6725f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro selectionSb.append(" AND " + RawContacts.DATA_SET + " IS NULL"); 6726f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } else { 672743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro selectionSb.append(" AND " + RawContacts.DATA_SET + "=") 672843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .append(DatabaseUtils.sqlEscapeString(dataSet)); 672943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 6730e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 6731e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 6732e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 6733e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 6734e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 6735e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 6736e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 6737e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 6738e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 6739e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 6740e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 67417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 6742c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 6743c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 6744c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 6745c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 6746c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 6747f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String getLimit(Uri uri) { 67482e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov String limitParam = getQueryParameter(uri, ContactsContract.LIMIT_PARAM_KEY); 6749c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 6750c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 6751c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6752c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 6753c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 6754c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 6755c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 6756c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 6757c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 6758c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6759c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 6760c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 6761c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 6762c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 6763c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6764c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6765c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 6766b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 6767f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 6768f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (mode.equals("r")) { 6769f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro waitForAccess(mReadAccessLatch); 6770f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 6771f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro waitForAccess(mWriteAccessLatch); 6772f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 67735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 67745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 67755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileProvider.openAssetFile(uri, mode); 67765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 67775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 67785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mode.equals("r")) { 67795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDb = mDbHelper.get().getReadableDatabase(); 67805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 67815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDb = mDbHelper.get().getWritableDatabase(); 67825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 67835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return openAssetFileLocal(uri, mode); 67845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 67855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 67865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 67875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public AssetFileDescriptor openAssetFileLocal(Uri uri, String mode) 67885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throws FileNotFoundException { 67895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 67905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 67915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 67925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 67935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 6794415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 6795b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 6796b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 6797a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 679824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 67995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return openPhotoAssetFile(mActiveDb.get(), uri, mode, 680024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Data._ID + "=" + Contacts.PHOTO_ID + " AND " + 680124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro RawContacts.CONTACT_ID + "=?", 680224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro new String[]{String.valueOf(rawContactId)}); 6803e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 6804b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 6805f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_ID_DISPLAY_PHOTO: { 6806f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (!mode.equals("r")) { 6807f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new IllegalArgumentException( 6808f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Display photos retrieved by contact ID can only be read."); 6809f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6810f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long contactId = Long.parseLong(uri.getPathSegments().get(1)); 68115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.CONTACTS, 6812f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro new String[]{Contacts.PHOTO_FILE_ID}, 6813f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Contacts._ID + "=?", new String[]{String.valueOf(contactId)}, 6814f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro null, null, null); 6815f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6816f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 6817f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = c.getLong(0); 6818f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 6819f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 6820f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 6821f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6822f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6823f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6824f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_DISPLAY_PHOTO: 6825f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_ID_DISPLAY_PHOTO: { 6826f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (!mode.equals("r")) { 6827f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new IllegalArgumentException( 6828f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Display photos retrieved by contact lookup key can only be read."); 6829f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6830f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro List<String> pathSegments = uri.getPathSegments(); 6831f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro int segmentCount = pathSegments.size(); 6832f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (segmentCount < 4) { 68335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 6834f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Missing a lookup key", uri)); 6835f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6836f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String lookupKey = pathSegments.get(2); 6837f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String[] projection = new String[]{Contacts.PHOTO_FILE_ID}; 6838f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (segmentCount == 5) { 6839f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long contactId = Long.parseLong(pathSegments.get(3)); 6840f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 6841f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 68425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 6843f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro projection, null, null, null, null, null, 6844f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey); 6845f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (c != null) { 6846f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6847f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 6848f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = c.getLong(c.getColumnIndex(Contacts.PHOTO_FILE_ID)); 6849f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 6850f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 6851f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 6852f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6853f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6854f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6855f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6856f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 6857f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro setTablesAndProjectionMapForContacts(qb, uri, projection); 68585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 68595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), projection, Contacts._ID + "=?", 6860f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro new String[]{String.valueOf(contactId)}, null, null, null); 6861f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6862f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 6863f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = c.getLong(c.getColumnIndex(Contacts.PHOTO_FILE_ID)); 6864f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 6865f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 6866f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 6867f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6868f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6869f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6870f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case RAW_CONTACTS_ID_DISPLAY_PHOTO: { 6871f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 6872f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro boolean writeable = !mode.equals("r"); 6873f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6874f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Find the primary photo data record for this raw contact. 6875f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 6876f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String[] projection = new String[]{Data._ID, Photo.PHOTO_FILE_ID}; 6877f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro setTablesAndProjectionMapForData(qb, uri, projection, false); 68787cf50494501938f175d288077145acf49da8f171Daniel Lehmann long photoMimetypeId = mDbHelper.get().getMimeTypeId(Photo.CONTENT_ITEM_TYPE); 68795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), projection, 68807cf50494501938f175d288077145acf49da8f171Daniel Lehmann Data.RAW_CONTACT_ID + "=? AND " + DataColumns.MIMETYPE_ID + "=?", 68817cf50494501938f175d288077145acf49da8f171Daniel Lehmann new String[]{String.valueOf(rawContactId), String.valueOf(photoMimetypeId)}, 6882f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro null, null, Data.IS_PRIMARY + " DESC"); 6883f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long dataId = 0; 6884f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = 0; 6885f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6886f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (c.getCount() >= 1) { 6887f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 6888f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro dataId = c.getLong(0); 6889f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro photoFileId = c.getLong(1); 6890f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6891f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 6892f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 6893f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6894f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6895f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // If writeable, open a writeable file descriptor that we can monitor. 6896f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // When the caller finishes writing content, we'll process the photo and 6897f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // update the data record. 6898f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (writeable) { 6899f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForWrite(rawContactId, dataId, uri, mode); 6900f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 6901f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 6902f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6903f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6904f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6905f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case DISPLAY_PHOTO: { 6906f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = ContentUris.parseId(uri); 6907f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (!mode.equals("r")) { 6908f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new IllegalArgumentException( 6909f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Display photos retrieved by key can only be read."); 6910f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6911f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 6912f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6913f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6914e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov case DATA_ID: { 691524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long dataId = Long.parseLong(uri.getPathSegments().get(1)); 69167cf50494501938f175d288077145acf49da8f171Daniel Lehmann long photoMimetypeId = mDbHelper.get().getMimeTypeId(Photo.CONTENT_ITEM_TYPE); 69175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return openPhotoAssetFile(mActiveDb.get(), uri, mode, 69187cf50494501938f175d288077145acf49da8f171Daniel Lehmann Data._ID + "=? AND " + DataColumns.MIMETYPE_ID + "=" + photoMimetypeId, 691924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro new String[]{String.valueOf(dataId)}); 6920d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 6921d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 6922fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen case PROFILE_AS_VCARD: { 6923fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // When opening a contact as file, we pass back contents as a 6924fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // vCard-encoded stream. We build into a local buffer first, 6925fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // then pipe into MemoryFile once the exact size is known. 6926fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 6927fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(uri, localStream, null, null); 6928fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen return buildAssetFileDescriptor(localStream); 6929fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen } 693042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 6931fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen case CONTACTS_AS_VCARD: { 693242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // When opening a contact as file, we pass back contents as a 693342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // vCard-encoded stream. We build into a local buffer first, 693442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // then pipe into MemoryFile once the exact size is known. 693542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 6936fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(uri, localStream, null, null); 6937f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return buildAssetFileDescriptor(localStream); 693842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 693942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 694042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 694142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKeys = uri.getPathSegments().get(2); 694242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String[] loopupKeyList = lookupKeys.split(":"); 694342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final StringBuilder inBuilder = new StringBuilder(); 6944fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen Uri queryUri = Contacts.CONTENT_URI; 694542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann int index = 0; 6946fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen 6947d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // SQLite has limits on how many parameters can be used 6948d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // so the IDs are concatenated to a query string here instead 694942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann for (String lookupKey : loopupKeyList) { 695042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann if (index == 0) { 6951d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append("("); 695242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } else { 6953d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append(","); 695442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 69555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // TODO: Figure out what to do if the profile contact is in the list. 69565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 695724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro inBuilder.append(contactId); 695842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann index++; 695942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 696042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann inBuilder.append(')'); 696142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + " IN " + inBuilder.toString(); 6962d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 6963d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 6964d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 6965d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 6966d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 6967fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(queryUri, localStream, selection, null); 6968f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return buildAssetFileDescriptor(localStream); 6969d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 6970b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 6971b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 69725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new FileNotFoundException(mDbHelper.get().exceptionMessage( 69735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro "File does not exist", uri)); 6974b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 6975b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 6976b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 6977afc8e7ad6e5208db6c87b8500ecc1246ad966d62Dave Santoro private AssetFileDescriptor openPhotoAssetFile(SQLiteDatabase db, Uri uri, String mode, 6978afc8e7ad6e5208db6c87b8500ecc1246ad966d62Dave Santoro String selection, String[] selectionArgs) 6979e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throws FileNotFoundException { 6980e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov if (!"r".equals(mode)) { 69815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new FileNotFoundException(mDbHelper.get().exceptionMessage("Mode " + mode 6982e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov + " not supported.", uri)); 6983e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 6984e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 6985e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String sql = 6986ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann "SELECT " + Photo.PHOTO + " FROM " + Views.DATA + 6987e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov " WHERE " + selection; 698808ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood try { 6989f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor( 6990f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert DatabaseUtils.blobFileDescriptorForQuery(db, sql, selectionArgs)); 699108ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } catch (SQLiteDoneException e) { 699208ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood // this will happen if the DB query returns no rows (i.e. contact does not exist) 699308ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood throw new FileNotFoundException(uri.toString()); 699408ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } 6995e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 6996e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 6997f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 6998f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Opens a display photo from the photo store for reading. 6999f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param photoFileId The display photo file ID 7000f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @return An asset file descriptor that allows the file to be read. 7001f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @throws FileNotFoundException If no photo file for the given ID exists. 7002f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 7003f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private AssetFileDescriptor openDisplayPhotoForRead(long photoFileId) 7004f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throws FileNotFoundException { 70055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PhotoStore.Entry entry = mPhotoStore.get().get(photoFileId); 7006f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (entry != null) { 7007f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return makeAssetFileDescriptor( 7008f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ParcelFileDescriptor.open(new File(entry.path), 7009f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ParcelFileDescriptor.MODE_READ_ONLY), 7010f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro entry.size); 7011f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 7012f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS); 7013f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new FileNotFoundException("No photo file found for ID " + photoFileId); 7014f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7015f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7016f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7017f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 7018f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Opens a file descriptor for a photo to be written. When the caller completes writing 7019f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * to the file (closing the output stream), the image will be parsed out and processed. 7020f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * If processing succeeds, the given raw contact ID's primary photo record will be 7021f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * populated with the inserted image (if no primary photo record exists, the data ID can 7022f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * be left as 0, and a new data record will be inserted). 7023f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param rawContactId Raw contact ID this photo entry should be associated with. 7024f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param dataId Data ID for a photo mimetype that will be updated with the inserted 7025f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * image. May be set to 0, in which case the inserted image will trigger creation 7026f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * of a new primary photo image data row for the raw contact. 7027f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param uri The URI being used to access this file. 7028f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param mode Read/write mode string. 7029f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @return An asset file descriptor the caller can use to write an image file for the 7030f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * raw contact. 7031f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 7032f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private AssetFileDescriptor openDisplayPhotoForWrite(long rawContactId, long dataId, Uri uri, 7033f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String mode) { 7034f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 7035c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro ParcelFileDescriptor[] pipeFds = ParcelFileDescriptor.createPipe(); 7036c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro PipeMonitor pipeMonitor = new PipeMonitor(rawContactId, dataId, pipeFds[0]); 7037c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro pipeMonitor.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[]) null); 7038c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro return new AssetFileDescriptor(pipeFds[1], 0, AssetFileDescriptor.UNKNOWN_LENGTH); 7039f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } catch (IOException ioe) { 7040f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Log.e(TAG, "Could not create temp image file in mode " + mode); 7041f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return null; 7042f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7043f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7044f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7045f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 7046c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro * Async task that monitors the given file descriptor (the read end of a pipe) for 7047c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro * the writer finishing. If the data from the pipe contains a valid image, the image 7048c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro * is either inserted into the given raw contact or updated in the given data row. 7049f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 7050c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro private class PipeMonitor extends AsyncTask<Object, Object, Object> { 7051c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro private final ParcelFileDescriptor mDescriptor; 7052f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private final long mRawContactId; 7053f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private final long mDataId; 7054c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro private PipeMonitor(long rawContactId, long dataId, ParcelFileDescriptor descriptor) { 7055f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mRawContactId = rawContactId; 7056f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mDataId = dataId; 7057c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro mDescriptor = descriptor; 7058f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7059f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7060f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro @Override 7061c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro protected Object doInBackground(Object... params) { 7062c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro AutoCloseInputStream is = new AutoCloseInputStream(mDescriptor); 7063f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 7064c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro Bitmap b = BitmapFactory.decodeStream(is); 7065f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (b != null) { 7066fa4db3db4146a26f154ef2e89352ad70a5415b8eDaniel Lehmann waitForAccess(mWriteAccessLatch); 7067f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro PhotoProcessor processor = new PhotoProcessor(b, mMaxDisplayPhotoDim, 7068f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mMaxThumbnailPhotoDim); 7069f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7070f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Store the compressed photo in the photo store. 70715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PhotoStore photoStore = ContactsContract.isProfileId(mRawContactId) 70725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ? mProfilePhotoStore 70735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro : mContactsPhotoStore; 70745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long photoFileId = photoStore.insert(processor); 7075f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7076c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro // Depending on whether we already had a data row to attach the photo 7077c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro // to, do an update or insert. 7078f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (mDataId != 0) { 7079f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Update the data record with the new photo. 7080f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ContentValues updateValues = new ContentValues(); 7081f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7082f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Signal that photo processing has already been handled. 7083f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.put(DataRowHandlerForPhoto.SKIP_PROCESSING_KEY, true); 7084f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7085f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (photoFileId != 0) { 7086f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.put(Photo.PHOTO_FILE_ID, photoFileId); 7087f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7088f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.put(Photo.PHOTO, processor.getThumbnailPhotoBytes()); 7089c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro update(ContentUris.withAppendedId(Data.CONTENT_URI, mDataId), 7090c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro updateValues, null, null); 7091f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 7092f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Insert a new primary data record with the photo. 7093f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ContentValues insertValues = new ContentValues(); 7094f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7095f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Signal that photo processing has already been handled. 7096f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(DataRowHandlerForPhoto.SKIP_PROCESSING_KEY, true); 7097f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7098f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 7099f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Data.IS_PRIMARY, 1); 7100f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (photoFileId != 0) { 7101f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Photo.PHOTO_FILE_ID, photoFileId); 7102f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7103f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Photo.PHOTO, processor.getThumbnailPhotoBytes()); 7104f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insert(RawContacts.CONTENT_URI.buildUpon() 7105f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .appendPath(String.valueOf(mRawContactId)) 7106f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .appendPath(RawContacts.Data.CONTENT_DIRECTORY).build(), 7107f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues); 7108f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7109c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro 7110f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7111c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro } catch (IOException e) { 7112c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro throw new RuntimeException(e); 7113f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7114c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro return null; 7115f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7116f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7117f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7118d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 7119d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7120d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 7121f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert * Returns an {@link AssetFileDescriptor} backed by the 7122d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 7123d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 7124f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 7125d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 7126d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 7127d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7128d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 7129d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7130f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor( 7131f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert ParcelFileDescriptor.fromData(byteData, CONTACT_MEMORY_FILE_NAME), 7132f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert byteData.length); 7133d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 7134ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert Log.w(TAG, "Problem writing stream into an ParcelFileDescriptor: " + e.toString()); 7135ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert return null; 7136d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7137d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7138d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7139f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor makeAssetFileDescriptor(ParcelFileDescriptor fd) { 7140f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor(fd, AssetFileDescriptor.UNKNOWN_LENGTH); 7141f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 7142f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 7143f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor makeAssetFileDescriptor(ParcelFileDescriptor fd, long length) { 7144f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return fd != null ? new AssetFileDescriptor(fd, 0, length) : null; 7145f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 7146f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 7147d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 7148d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 7149d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 7150d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 7151d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 7152fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen private void outputRawContactsAsVCard(Uri uri, OutputStream stream, 7153fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen String selection, String[] selectionArgs) { 7154d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 7155dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen int vcardconfig = VCardConfig.VCARD_TYPE_DEFAULT; 7156fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen if(uri.getBooleanQueryParameter( 7157fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen Contacts.QUERY_PARAMETER_VCARD_NO_PHOTO, false)) { 7158dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen vcardconfig |= VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT; 7159dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen } 71607a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa final VCardComposer composer = 7161dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen new VCardComposer(context, vcardconfig, false); 7162108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Writer writer = null; 7163108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa try { 7164108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer = new BufferedWriter(new OutputStreamWriter(stream)); 7165fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen if (!composer.init(uri, selection, selectionArgs, null)) { 7166108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.w(TAG, "Failed to init VCardComposer"); 7167108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return; 7168108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 7169d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7170108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa while (!composer.isAfterLast()) { 7171108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer.write(composer.createOneEntry()); 7172108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 7173108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } catch (IOException e) { 7174108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.e(TAG, "IOException: " + e); 7175108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } finally { 7176108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa composer.terminate(); 7177108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa if (writer != null) { 7178108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa try { 7179108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer.close(); 7180108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } catch (IOException e) { 7181108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.w(TAG, "IOException during closing output stream: " + e); 7182108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 7183d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7184d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7185d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7186b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 71874f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 71884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 7189415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 7190415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov waitForAccess(mReadAccessLatch); 7191415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 7192a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 71934f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 7194b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 7195be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 71962d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill case CONTACTS_LOOKUP: 7197b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 7198b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 719924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: 7200b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 7201f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 720242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: 720324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: 7204f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 7205f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov case CONTACTS_ID_PHOTO: 7206f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_ID_DISPLAY_PHOTO: 7207f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_DISPLAY_PHOTO: 7208f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_ID_DISPLAY_PHOTO: 7209f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case RAW_CONTACTS_ID_DISPLAY_PHOTO: 7210f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case DISPLAY_PHOTO: 7211f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return "image/jpeg"; 7212b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 721324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS: 7214be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 7215b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 721624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID: 7217b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 7218f481f22a9323fe338672f99b88b26c5f0725cd42David Brown case DATA: 721924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_DATA: 7220f481f22a9323fe338672f99b88b26c5f0725cd42David Brown return Data.CONTENT_TYPE; 7221508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 72225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long id = ContentUris.parseId(uri); 72235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (ContactsContract.isProfileId(id)) { 72245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileHelper.getDataMimeType(id); 72255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 72265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mContactsHelper.getDataMimeType(id); 72275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 722848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 722948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 723048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 723148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 72329005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov case PHONE_LOOKUP: 72339005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov return PhoneLookup.CONTENT_TYPE; 723448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 723548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 723648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 723748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 723848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 723948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 724048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 724148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 7242b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 7243b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 7244b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 7245b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 7246b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 7247b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 7248b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 7249b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 7250c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 7251c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 7252c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 7253c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 7254d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES: 7255d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_TYPE; 7256d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID: 7257d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_ITEM_TYPE; 7258af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS: 7259af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.CONTENT_TYPE; 7260af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_ID: 7261af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.CONTENT_ITEM_TYPE; 7262af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_ID_PHOTOS: 7263af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.StreamItemPhotos.CONTENT_TYPE; 7264af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_ID_PHOTOS_ID: 7265af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.StreamItemPhotos.CONTENT_ITEM_TYPE; 7266af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_PHOTOS: 7267af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki throw new UnsupportedOperationException("Not supported for write-only URI " + uri); 726861efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 726961efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 72704f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 72714f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 72727e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 727309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov public String[] getDefaultProjection(Uri uri) { 727409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov final int match = sUriMatcher.match(uri); 727509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov switch (match) { 727609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS: 727709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP: 727809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_ID: 727909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP_ID: 728009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 728124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: 728209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsProjectionMap.getColumnNames(); 728309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 72848727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov case CONTACTS_ID_ENTITIES: 728524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_ENTITIES: 72868727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov return sEntityProjectionMap.getColumnNames(); 72878727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov 728809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_VCARD: 728909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_MULTI_VCARD: 729024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: 729109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsVCardProjectionMap.getColumnNames(); 729209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 729309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS: 729409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS_ID: 729524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS: 729624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID: 729709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sRawContactsProjectionMap.getColumnNames(); 729809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 729909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DATA_ID: 730009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES: 730109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES_ID: 730209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS: 730309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS_ID: 730409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS: 730509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS_ID: 730624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_DATA: 730709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDataProjectionMap.getColumnNames(); 730809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 730909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONE_LOOKUP: 731009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sPhoneLookupProjectionMap.getColumnNames(); 731109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 731209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 731309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 731409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sAggregationExceptionsProjectionMap.getColumnNames(); 731509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 731609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case SETTINGS: 731709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sSettingsProjectionMap.getColumnNames(); 731809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 731909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES: 732009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES_ID: 732109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDirectoryProjectionMap.getColumnNames(); 732209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 732309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov default: 732409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return null; 732509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 732609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 732709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 7328f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 7329f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 7330f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 7331f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 7332f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7333f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 7334f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 7335f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 7336f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 73375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().insertNameLookup(rawContactId, dataId, lookupType, name); 7338f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7339f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 7340f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 7341f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 7342d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov return mCommonNicknameCache.getCommonNicknameClusters(normalizedName); 7343f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7344f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7345f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 73462d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 7347d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 7348d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 7349d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 7350d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 7351d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 7352d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 7353d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 7354e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 7355916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 7356916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + "))"); 7357e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 7358e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 73599a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov public boolean isPhoneNumber(String filter) { 73609a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov boolean atLeastOneDigit = false; 73619a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov int len = filter.length(); 73629a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov for (int i = 0; i < len; i++) { 73639a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov char c = filter.charAt(i); 73649a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (c >= '0' && c <= '9') { 73659a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov atLeastOneDigit = true; 73669a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } else if (c != '*' && c != '#' && c != '+' && c != 'N' && c != '.' && c != ';' 73679a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov && c != '-' && c != '(' && c != ')' && c != ' ') { 73689a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return false; 73699a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 73709a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 73719a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return atLeastOneDigit; 73729a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 73739a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 73744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 73757a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * Takes components of a name from the query parameters and returns a cursor with those 73767a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * components as well as all missing components. There is no database activity involved 73777a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * in this so the call can be made on the UI thread. 73787a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov */ 73797a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private Cursor completeName(Uri uri, String[] projection) { 73807a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (projection == null) { 73817a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov projection = sDataProjectionMap.getColumnNames(); 73827a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 73837a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 73847a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ContentValues values = new ContentValues(); 7385f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov DataRowHandlerForStructuredName handler = (DataRowHandlerForStructuredName) 7386f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov getDataRowHandler(StructuredName.CONTENT_ITEM_TYPE); 73877a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 73887a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov copyQueryParamsToContentValues(values, uri, 73897a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.DISPLAY_NAME, 73907a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PREFIX, 73917a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.GIVEN_NAME, 73927a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.MIDDLE_NAME, 73937a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.FAMILY_NAME, 73947a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.SUFFIX, 73957a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_NAME, 73967a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_FAMILY_NAME, 73977a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_MIDDLE_NAME, 73987a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_GIVEN_NAME 73997a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ); 74007a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74017a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov handler.fixStructuredNameComponents(values, values); 74027a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74037a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 74047a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov Object[] row = new Object[projection.length]; 74057a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (int i = 0; i < projection.length; i++) { 74067a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov row[i] = values.get(projection[i]); 74077a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74087a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov cursor.addRow(row); 74097a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return cursor; 74107a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74117a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74127a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private void copyQueryParamsToContentValues(ContentValues values, Uri uri, String... columns) { 74137a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (String column : columns) { 74147a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov String param = uri.getQueryParameter(column); 74157a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (param != null) { 74167a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov values.put(column, param); 74177a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74187a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74197a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74207a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74217a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74227a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov /** 74234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 74244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 74254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 7426b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 7427b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 7428b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 7429b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 7430b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 74314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 74324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 7433b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 7434b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 7435b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 7436caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 74375e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 74385e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 74395e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 74405e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 74415e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 74425e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 74435e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 74445e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 74455e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 74465e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 74475e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 7448caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 7449caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 7450caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 74515f1f4a062ac34d75d2dbf586702cbeb121cf09caDmitri Plotnikov Account[] accounts = accountManager.getAccountsByType(DEFAULT_ACCOUNT_TYPE); 7452caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 7453caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 7454caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 7455caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 74566f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 7457caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 74586f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 7459caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 7460f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 746173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov /** 746243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * Returns true if the specified account type and data set is writable. 746373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov */ 746443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro protected boolean isWritableAccountWithDataSet(String accountTypeAndDataSet) { 746543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (accountTypeAndDataSet == null) { 7466bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov return true; 7467bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov } 7468bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov 746943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Boolean writable = mAccountWritability.get(accountTypeAndDataSet); 747073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable != null) { 747173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 747273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 747373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 7474627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov IContentService contentService = ContentResolver.getContentService(); 7475627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 747643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // TODO(dsantoro): Need to update this logic to allow for sub-accounts. 7477627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 7478627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (ContactsContract.AUTHORITY.equals(sync.authority) && 747943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountTypeAndDataSet.equals(sync.accountType)) { 748073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = sync.supportsUploading(); 748173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov break; 7482627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 7483627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 7484627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } catch (RemoteException e) { 7485627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 7486627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 748773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 748873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable == null) { 748973f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = false; 749073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 749173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 749243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro mAccountWritability.put(accountTypeAndDataSet, writable); 749373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 7494627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 7495b4e61e064b59e8076df81b061add9fb358fd2ed9Dmitri Plotnikov 7496d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 7497f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static boolean readBooleanQueryParameter(Uri uri, String parameter, 7498f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean defaultValue) { 7499f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7500f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // Manually parse the query, which is much faster than calling uri.getQueryParameter 7501f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 7502f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 7503f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 7504f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7505f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7506f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = query.indexOf(parameter); 7507f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 7508f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 7509f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7510f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7511f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameter.length(); 7512f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7513f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return !matchQueryParameter(query, index, "=0", false) 7514f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && !matchQueryParameter(query, index, "=false", true); 7515f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7516f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7517f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private static boolean matchQueryParameter(String query, int index, String value, 7518f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean ignoreCase) { 7519f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int length = value.length(); 7520f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return query.regionMatches(ignoreCase, index, value, 0, length) 7521f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && (query.length() == index + length || query.charAt(index + length) == '&'); 7522f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7523f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7524f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /** 7525f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * A fast re-implementation of {@link Uri#getQueryParameter} 7526f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov */ 7527f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static String getQueryParameter(Uri uri, String parameter) { 7528f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 7529f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 7530f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 7531f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7532f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7533f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int queryLength = query.length(); 7534f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int parameterLength = parameter.length(); 7535f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7536f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String value; 7537f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = 0; 7538f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov while (true) { 7539f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index = query.indexOf(parameter, index); 7540f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 7541f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 75425fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa } 75435fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa 75445fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // Should match against the whole parameter instead of its suffix. 75455fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // e.g. The parameter "param" must not be found in "some_param=val". 75465fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa if (index > 0) { 75475fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa char prevChar = query.charAt(index - 1); 75485fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa if (prevChar != '?' && prevChar != '&') { 75495fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // With "some_param=val1¶m=val2", we should find second "param" occurrence. 75505fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa index += parameterLength; 75515fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa continue; 75525fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa } 7553f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7554f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7555f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameterLength; 7556f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7557f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (queryLength == index) { 7558f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 7559f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7560f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7561f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query.charAt(index) == '=') { 7562f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index++; 7563f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov break; 7564f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7565f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7566f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7567f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int ampIndex = query.indexOf('&', index); 7568f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (ampIndex == -1) { 7569f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index); 7570f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 7571f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index, ampIndex); 7572f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7573f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7574f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return Uri.decode(value); 7575f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 75765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 75770dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov protected boolean isAggregationUpgradeNeeded() { 75780dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 75790dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return false; 75800dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 75810dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 75825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int version = Integer.parseInt(mContactsHelper.getProperty( 75835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROPERTY_AGGREGATION_ALGORITHM, "1")); 75840dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return version < PROPERTY_AGGREGATION_ALGORITHM_VERSION; 75850dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 75860dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 7587bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void upgradeAggregationAlgorithmInBackground() { 75880dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov // This upgrade will affect very few contacts, so it can be performed on the 75890dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov // main thread during the initial boot after an OTA 75900dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 75910dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Log.i(TAG, "Upgrading aggregation algorithm"); 75920dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov int count = 0; 75930dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long start = SystemClock.currentThreadTimeMillis(); 75945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = null; 75950dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov try { 75965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 75975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db = mContactsHelper.getWritableDatabase(); 75985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(db); 75995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.beginTransaction(); 76005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = db.query(true, 76010dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Tables.RAW_CONTACTS + " r1 JOIN " + Tables.RAW_CONTACTS + " r2", 76020dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov new String[]{"r1." + RawContacts._ID}, 76030dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov "r1." + RawContacts._ID + "!=r2." + RawContacts._ID + 76040dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.CONTACT_ID + "=r2." + RawContacts.CONTACT_ID + 76050dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.ACCOUNT_NAME + "=r2." + RawContacts.ACCOUNT_NAME + 760643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND r1." + RawContacts.ACCOUNT_TYPE + "=r2." + RawContacts.ACCOUNT_TYPE + 760743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND r1." + RawContacts.DATA_SET + "=r2." + RawContacts.DATA_SET, 76080dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov null, null, null, null, null); 76090dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov try { 76100dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov while (cursor.moveToNext()) { 76110dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long rawContactId = cursor.getLong(0); 76120dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, 76130dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 76140dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov count++; 76150dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 76160dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } finally { 76170dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov cursor.close(); 76180dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 76195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactAggregator.aggregateInTransaction(mTransactionContext.get(), db); 7620bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 76215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.setTransactionSuccessful(); 76225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setProperty(PROPERTY_AGGREGATION_ALGORITHM, 76230dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov String.valueOf(PROPERTY_AGGREGATION_ALGORITHM_VERSION)); 76240dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } finally { 76255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (db != null) { 76265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.endTransaction(); 76275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 76280dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long end = SystemClock.currentThreadTimeMillis(); 76290dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Log.i(TAG, "Aggregation algorithm upgraded for " + count 76300dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov + " contacts, in " + (end - start) + "ms"); 76310dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 76320dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 76339a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 76349a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov /* Visible for testing */ 76359a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov boolean isPhone() { 76369a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (!sIsPhoneInitialized) { 76379a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sIsPhone = new TelephonyManager(getContext()).isVoiceCapable(); 76389a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sIsPhoneInitialized = true; 76399a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 76409a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return sIsPhone; 76419a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 764246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 764346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private boolean handleDataUsageFeedback(Uri uri) { 764446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final long currentTimeMillis = System.currentTimeMillis(); 764546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String usageType = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 764646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] ids = uri.getLastPathSegment().trim().split(","); 764746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final ArrayList<Long> dataIds = new ArrayList<Long>(); 764846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 764946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa for (String id : ids) { 765046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa dataIds.add(Long.valueOf(id)); 765146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 765246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final boolean successful; 765346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (TextUtils.isEmpty(usageType)) { 765446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Log.w(TAG, "Method for data usage feedback isn't specified. Ignoring."); 765546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa successful = false; 765646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 765746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa successful = updateDataUsageStat(dataIds, usageType, currentTimeMillis) > 0; 765846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 765946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 766046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa // Handle old API. This doesn't affect the result of this entire method. 766146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] questionMarks = new String[ids.length]; 766246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Arrays.fill(questionMarks, "?"); 766346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String where = Data._ID + " IN (" + TextUtils.join(",", questionMarks) + ")"; 76645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final Cursor cursor = mActiveDb.get().query( 7665ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann Views.DATA, 766646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { Data.CONTACT_ID }, 766746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa where, ids, null, null, null); 766846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 766946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa while (cursor.moveToNext()) { 767046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa mSelectionArgs1[0] = cursor.getString(0); 767146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa ContentValues values2 = new ContentValues(); 767246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values2.put(Contacts.LAST_TIME_CONTACTED, currentTimeMillis); 76735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().update(Tables.CONTACTS, values2, Contacts._ID + "=?", 76745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mSelectionArgs1); 76755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 76765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 767746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 767846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 767946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa cursor.close(); 768046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 768146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 768246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return successful; 768346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 768446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 768546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 768646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Update {@link Tables#DATA_USAGE_STAT}. 768746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * 768846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * @return the number of rows affected. 768946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 7690f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa @VisibleForTesting 7691f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa /* package */ int updateDataUsageStat( 7692f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa List<Long> dataIds, String type, long currentTimeMillis) { 769346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final int typeInt = sDataUsageTypeMap.get(type); 769446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String where = DataUsageStatColumns.DATA_ID + " =? AND " 769546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + DataUsageStatColumns.USAGE_TYPE_INT + " =?"; 769646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] columns = 769746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { DataUsageStatColumns._ID, DataUsageStatColumns.TIMES_USED }; 769846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final ContentValues values = new ContentValues(); 769946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa for (Long dataId : dataIds) { 770046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] args = new String[] { dataId.toString(), String.valueOf(typeInt) }; 77015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().beginTransaction(); 770246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 77035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final Cursor cursor = mActiveDb.get().query(Tables.DATA_USAGE_STAT, columns, where, 77045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro args, null, null, null); 770546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 770646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (cursor.getCount() > 0) { 770746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!cursor.moveToFirst()) { 770846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Log.e(TAG, 770946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa "moveToFirst() failed while getAccount() returned non-zero."); 771046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 771146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.clear(); 771246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.TIMES_USED, cursor.getInt(1) + 1); 771346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.LAST_TIME_USED, currentTimeMillis); 77145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().update(Tables.DATA_USAGE_STAT, values, 771546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns._ID + " =?", 771646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { cursor.getString(0) }); 771746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 771846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 771946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.clear(); 772046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.DATA_ID, dataId); 772146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.USAGE_TYPE_INT, typeInt); 772246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.TIMES_USED, 1); 772346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.LAST_TIME_USED, currentTimeMillis); 77245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().insert(Tables.DATA_USAGE_STAT, null, values); 772546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 77265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().setTransactionSuccessful(); 772746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 772846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa cursor.close(); 772946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 773046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 77315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().endTransaction(); 773246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 773346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 773446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 773546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return dataIds.size(); 773646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 773746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 773846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 773946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Returns a sort order String for promoting data rows (email addresses, phone numbers, etc.) 774046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * associated with a primary account. The primary account should be supplied from applications 774146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * with {@link ContactsContract#PRIMARY_ACCOUNT_NAME} and 774246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * {@link ContactsContract#PRIMARY_ACCOUNT_TYPE}. Null will be returned when the primary 774346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * account isn't available. 774446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 774546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private String getAccountPromotionSortOrder(Uri uri) { 774646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String primaryAccountName = 774746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa uri.getQueryParameter(ContactsContract.PRIMARY_ACCOUNT_NAME); 774846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String primaryAccountType = 774946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa uri.getQueryParameter(ContactsContract.PRIMARY_ACCOUNT_TYPE); 775046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 775146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa // Data rows associated with primary account should be promoted. 775246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(primaryAccountName)) { 775346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa StringBuilder sb = new StringBuilder(); 775446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append("(CASE WHEN " + RawContacts.ACCOUNT_NAME + "="); 775546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DatabaseUtils.appendEscapedSQLString(sb, primaryAccountName); 775646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(primaryAccountType)) { 775746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" AND " + RawContacts.ACCOUNT_TYPE + "="); 775846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DatabaseUtils.appendEscapedSQLString(sb, primaryAccountType); 775946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 776046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" THEN 0 ELSE 1 END)"); 776146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return sb.toString(); 776246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 776346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return null; 776446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 776546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 7766b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 7767b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson /** 7768b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * Checks the URI for a deferred snippeting request 7769b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * @return a boolean indicating if a deferred snippeting request is in the RI 7770b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson */ 7771b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private boolean deferredSnippetingRequested(Uri uri) { 7772b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson String deferredSnippeting = 7773b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson getQueryParameter(uri, SearchSnippetColumns.DEFERRED_SNIPPETING_KEY); 7774b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return !TextUtils.isEmpty(deferredSnippeting) && deferredSnippeting.equals("1"); 7775b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 7776b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 7777b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson /** 7778b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * Checks if query is a single word or not. 7779b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * @return a boolean indicating if the query is one word or not 7780b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson */ 7781b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private boolean isSingleWordQuery(String query) { 7782b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return query.split(QUERY_TOKENIZER_REGEX).length == 1; 7783b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 7784b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 7785b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson /** 7786b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * Checks the projection for a SNIPPET column indicating that a snippet is needed 7787b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * @return a boolean indicating if a snippet is needed or not. 7788b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson */ 7789b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private boolean snippetNeeded(String [] projection) { 7790b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return mDbHelper.get().isInProjection(projection, SearchSnippetColumns.SNIPPET); 7791b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 77924f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 7793