ContactsProvider2.java revision bd20dbedba706fdf2db7acb1c7d4391e57129d44
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; 263bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_PHOTO = 1010; 264bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ID_PHOTO = 1011; 265bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_ID_DISPLAY_PHOTO = 1012; 266bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_DISPLAY_PHOTO = 1013; 267bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ID_DISPLAY_PHOTO = 1014; 268bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_AS_VCARD = 1015; 269bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_AS_MULTI_VCARD = 1016; 270bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_DATA = 1017; 271bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ID_DATA = 1018; 272bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_ID_ENTITIES = 1019; 273bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ENTITIES = 1020; 274bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ID_ENTITIES = 1021; 275bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_ID_STREAM_ITEMS = 1022; 276bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_STREAM_ITEMS = 1023; 277bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_LOOKUP_ID_STREAM_ITEMS = 1024; 278bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro private static final int CONTACTS_FREQUENT = 1025; 2794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 2815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 2825ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 28346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 284f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int RAW_CONTACTS_ID_DISPLAY_PHOTO = 2006; 285f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int RAW_CONTACTS_ID_STREAM_ITEMS = 2007; 28682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro private static final int RAW_CONTACTS_ID_STREAM_ITEMS_ID = 2008; 2874f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2886bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 2896bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 290ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 29148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 29248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 29348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 29448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 29548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 29648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 29748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 29848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 299a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 3006bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 3016bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 302b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 303b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 304b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 30582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 30682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 3071f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 30831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 30931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 310eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 311eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 312ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 313ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 314ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 315ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 31635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 317b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 3185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final int PROFILE_SYNCSTATE = 11002; 3195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final int PROFILE_SYNCSTATE_ID = 11003; 32035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 321c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 322c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 323c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3241b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 3251b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 3261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 3271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 3281b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 32946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 33046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 33109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private static final int PROVIDER_STATUS = 16001; 33209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 333d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES = 17001; 334d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES_ID = 17002; 335d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3367a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private static final int COMPLETE_NAME = 18000; 3377a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 33824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE = 19000; 33924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_ENTITIES = 19001; 34024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_DATA = 19002; 34124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_DATA_ID = 19003; 34224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_AS_VCARD = 19004; 34324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS = 19005; 34424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID = 19006; 34524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID_DATA = 19007; 34624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID_ENTITIES = 19008; 3475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final int PROFILE_STATUS_UPDATES = 19009; 3483202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro private static final int PROFILE_RAW_CONTACT_ENTITIES = 19010; 34924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 35046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final int DATA_USAGE_FEEDBACK_ID = 20001; 35146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 3523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS = 21000; 3533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_PHOTOS = 21001; 3543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID = 21002; 3553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID_PHOTOS = 21003; 3563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID_PHOTOS_ID = 21004; 3573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_LIMIT = 21005; 3583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 359f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int DISPLAY_PHOTO = 22000; 360f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int PHOTO_DIMENSIONS = 22001; 361f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 3625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Inserts into URIs in this map will direct to the profile database if the parent record's 3635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // value (looked up from the ContentValues object with the key specified by the value in this 3645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // map) is in the profile ID-space (see {@link ProfileDatabaseHelper#PROFILE_ID_SPACE}). 3655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final Map<Integer, String> INSERT_URI_ID_VALUE_MAP = Maps.newHashMap(); 3665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro static { 3675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(DATA, Data.RAW_CONTACT_ID); 3685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(RAW_CONTACTS_DATA, Data.RAW_CONTACT_ID); 3695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STATUS_UPDATES, StatusUpdates.DATA_ID); 3705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STREAM_ITEMS, StreamItems.RAW_CONTACT_ID); 3715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(RAW_CONTACTS_ID_STREAM_ITEMS, StreamItems.RAW_CONTACT_ID); 3725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STREAM_ITEMS_PHOTOS, StreamItemPhotos.STREAM_ITEM_ID); 3735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STREAM_ITEMS_ID_PHOTOS, StreamItemPhotos.STREAM_ITEM_ID); 3745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 3755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 376dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID = 377dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 378dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME 379dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 380dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE 38143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + "=" + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AND (" 38243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET 38343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + "=" + RawContactsColumns.CONCRETE_DATA_SET + " OR " 38443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET + " IS NULL AND " 38543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_DATA_SET + " IS NULL)" 386dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND " + Groups.FAVORITES + " != 0"; 387dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 388dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID = 389dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 390dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 391dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 392dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 39343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AND (" 39443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET + "=" 39543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_DATA_SET + " OR " 39643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET + " IS NULL AND " 39743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_DATA_SET + " IS NULL)" 39843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + " AND " + Groups.AUTO_ADD + " != 0"; 399dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 400dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String[] PROJECTION_GROUP_ID 401dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana = new String[]{Tables.GROUPS + "." + Groups._ID}; 402dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 403dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_GROUPMEMBERSHIP_DATA = DataColumns.MIMETYPE_ID + "=? " 404dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.GROUP_ROW_ID + "=? " 405dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.RAW_CONTACT_ID + "=?"; 406dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 407dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_STARRED_FROM_RAW_CONTACTS = 408dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana "SELECT " + RawContacts.STARRED 409dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?"; 410dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 411d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 412f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 413f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 414f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 41567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 41667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 4176cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 4186802030a777c0c3ba1dc029c534cca4784260632Dave Santoro RawContactsColumns.CONCRETE_ACCOUNT_TYPE, 4196802030a777c0c3ba1dc029c534cca4784260632Dave Santoro RawContactsColumns.CONCRETE_ACCOUNT_NAME, 42043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContactsColumns.CONCRETE_DATA_SET, 4213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 422f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 423ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 424ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 425d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 4266802030a777c0c3ba1dc029c534cca4784260632Dave Santoro public static final int ACCOUNT_TYPE = 1; 4276802030a777c0c3ba1dc029c534cca4784260632Dave Santoro public static final int ACCOUNT_NAME = 2; 42843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro public static final int DATA_SET = 3; 42943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro public static final int DATA_ID = 4; 43043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro public static final int CONTACT_ID = 5; 431ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4321f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 433f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov interface RawContactsQuery { 43419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 43519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 43619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 437ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.DELETED, 438ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 439ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_NAME, 44043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.DATA_SET, 44119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 44219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 44319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 444ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_TYPE = 1; 445ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_NAME = 2; 44643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int DATA_SET = 3; 44719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 44819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 449c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 450caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 45171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 45271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 45371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 45471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 45571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 45671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 45771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 45871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 4597cf50494501938f175d288077145acf49da8f171Daniel Lehmann + " WHERE " + DataColumns.MIMETYPE_ID + "=?" 4607cf50494501938f175d288077145acf49da8f171Daniel Lehmann + " AND " + GroupMembership.GROUP_ROW_ID + "=" 46171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 46271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 46371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 46471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 465a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating DIRTY flag on multiple raw contacts */ 466a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_DIRTY_SQL = 467a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 468a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.DIRTY + "=1" + 469a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 470a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 471a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating VERSION on multiple raw contacts */ 472a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_VERSION_SQL = 473a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 474a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + 475a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 476a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 477c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov // Current contacts - those contacted within the last 3 days (in seconds) 478c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final long EMAIL_FILTER_CURRENT = 3 * 24 * 60 * 60; 479c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 480c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov // Recent contacts - those contacted within the last 30 days (in seconds) 481c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final long EMAIL_FILTER_RECENT = 30 * 24 * 60 * 60; 482c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 483f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa private static final String TIME_SINCE_LAST_USED = 484f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa "(strftime('%s', 'now') - " + DataUsageStatColumns.LAST_TIME_USED + "/1000)"; 485f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa 486c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov /* 487c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * Sorting order for email address suggestions: first starred, then the rest. 4882262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * second in_visible_group, then the rest. 4892262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * Within the four (starred/unstarred, in_visible_group/not-in_visible_group) groups 4902262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * - three buckets: very recently contacted, then fairly 491c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * recently contacted, then the rest. Within each of the bucket - descending count 49246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * of times contacted (both for data row and for contact row). If all else fails, alphabetical. 49346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * (Super)primary email address is returned before other addresses for the same contact. 494c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov */ 495c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final String EMAIL_FILTER_SORT_ORDER = 4962262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa Contacts.STARRED + " DESC, " 4972262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa + Contacts.IN_VISIBLE_GROUP + " DESC, " 498f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa + "(CASE WHEN " + TIME_SINCE_LAST_USED + " < " + EMAIL_FILTER_CURRENT 49946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " THEN 0 " 500f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa + " WHEN " + TIME_SINCE_LAST_USED + " < " + EMAIL_FILTER_RECENT 50146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " THEN 1 " 50246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " ELSE 2 END), " 50346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + DataUsageStatColumns.TIMES_USED + " DESC, " 50446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + Contacts.DISPLAY_NAME + ", " 50546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + Data.CONTACT_ID + ", " 506c591cc2ffecdd0038f787a133606752752294c13Daisuke Miyakawa + Data.IS_SUPER_PRIMARY + " DESC, " 507c591cc2ffecdd0038f787a133606752752294c13Daisuke Miyakawa + Data.IS_PRIMARY + " DESC"; 50846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 50946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** Currently same as {@link #EMAIL_FILTER_SORT_ORDER} */ 51046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final String PHONE_FILTER_SORT_ORDER = EMAIL_FILTER_SORT_ORDER; 511c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 512916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Name lookup types used for contact filtering */ 513916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final String CONTACT_LOOKUP_NAME_TYPES = 514916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_COLLATION_KEY + "," + 515916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME + "," + 51692ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov NameLookupType.NICKNAME; 517916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 518f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov /** 519f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov * If any of these columns are used in a Data projection, there is no point in 520f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov * using the DISTINCT keyword, which can negatively affect performance. 521f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov */ 522f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov private static final String[] DISTINCT_DATA_PROHIBITING_COLUMNS = { 523f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data._ID, 524f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data.RAW_CONTACT_ID, 525f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data.NAME_RAW_CONTACT_ID, 526f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 527f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 52843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.DATA_SET, 52943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 530f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.DIRTY, 531f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.NAME_VERIFIED, 532f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.SOURCE_ID, 533f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.VERSION, 534f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov }; 535916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 536f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsColumns = ProjectionMap.builder() 537f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CUSTOM_RINGTONE) 538f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME) 539f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_ALTERNATIVE) 540f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_SOURCE) 541f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.IN_VISIBLE_GROUP) 542f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LAST_TIME_CONTACTED) 543f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LOOKUP_KEY) 544f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME) 545f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME_STYLE) 546f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHOTO_ID) 547f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .add(Contacts.PHOTO_FILE_ID) 5483d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(Contacts.PHOTO_URI) 5493d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(Contacts.PHOTO_THUMBNAIL_URI) 550f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SEND_TO_VOICEMAIL) 551f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_ALTERNATIVE) 552f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_PRIMARY) 553f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.STARRED) 554f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.TIMES_CONTACTED) 555cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 556f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 557f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 558f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsPresenceColumns = ProjectionMap.builder() 559f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 560f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE) 561f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 562f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 563f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 564f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 565f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 566f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 567f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 568f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 569f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 570f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 571f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 572f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 573f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 574f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 575f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSnippetColumns = ProjectionMap.builder() 57603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov .add(SearchSnippetColumns.SNIPPET) 577f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 578f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 579f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactColumns = ProjectionMap.builder() 580f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_NAME) 581f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_TYPE) 58243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(RawContacts.DATA_SET) 58343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(RawContacts.ACCOUNT_TYPE_AND_DATA_SET) 584f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DIRTY) 585f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.NAME_VERIFIED) 586f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SOURCE_ID) 587f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.VERSION) 588f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 589f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 590f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactSyncColumns = ProjectionMap.builder() 591f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC1) 592f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC2) 593f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC3) 594f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC4) 595f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 596f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 597f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataColumns = ProjectionMap.builder() 598f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA1) 599f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA2) 600f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA3) 601f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA4) 602f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA5) 603f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA6) 604f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA7) 605f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA8) 606f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA9) 607f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA10) 608f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA11) 609f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA12) 610f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA13) 611f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA14) 612f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA15) 613f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA_VERSION) 614f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_PRIMARY) 615f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_SUPER_PRIMARY) 616f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.MIMETYPE) 617f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RES_PACKAGE) 618f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC1) 619f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC2) 620f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC3) 621f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC4) 622f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(GroupMembership.GROUP_SOURCE_ID) 623f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 624f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 625f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactPresenceColumns = ProjectionMap.builder() 626f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 627f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.PRESENCE) 628f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 629f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.CHAT_CAPABILITY) 630f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 631f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 632f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 633f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 634f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 635f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 636f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 637f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 638f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 639f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 640f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 641f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 642f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataPresenceColumns = ProjectionMap.builder() 643f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.PRESENCE, Tables.PRESENCE + "." + StatusUpdates.PRESENCE) 644f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CHAT_CAPABILITY, Tables.PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 645f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS, StatusUpdatesColumns.CONCRETE_STATUS) 646f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_TIMESTAMP, StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 647f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_RES_PACKAGE, StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 648f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_LABEL, StatusUpdatesColumns.CONCRETE_STATUS_LABEL) 649f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_ICON, StatusUpdatesColumns.CONCRETE_STATUS_ICON) 650f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 651f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 652038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 653f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sCountProjectionMap = ProjectionMap.builder() 654f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(BaseColumns._COUNT, "COUNT(*)") 655f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 656f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 657e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 658f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionMap = ProjectionMap.builder() 659f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts._ID) 660f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 661f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.NAME_RAW_CONTACT_ID) 66224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(Contacts.IS_USER_PROFILE) 663f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 664f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsPresenceColumns) 665f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 666f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 667916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Contains just the contacts columns */ 668f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionWithSnippetMap = ProjectionMap.builder() 669f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 670f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sSnippetColumns) 671f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 672916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 6735e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 674f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentStarredProjectionMap = ProjectionMap.builder() 675f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 6762f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, String.valueOf(Long.MAX_VALUE)) 677f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 678f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 679f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentFrequentProjectionMap = ProjectionMap.builder() 680f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 6812f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, "SUM(" + DataUsageStatColumns.CONCRETE_TIMES_USED + ")") 682f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 683f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 6844928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa /** 6854928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * Used for Strequent Uri with {@link ContactsContract#STREQUENT_PHONE_ONLY}, which allows 6864928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * users to obtain part of Data columns. Right now Starred part just returns NULL for 6874928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * those data columns (frequent part should return real ones in data table). 6884928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa **/ 6894928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa private static final ProjectionMap sStrequentPhoneOnlyStarredProjectionMap 6904928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa = ProjectionMap.builder() 6914928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .addAll(sContactsProjectionMap) 6924928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, String.valueOf(Long.MAX_VALUE)) 6934928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.NUMBER, "NULL") 6944928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.TYPE, "NULL") 6954928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.LABEL, "NULL") 6964928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .build(); 6974928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 6984928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa /** 6994928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * Used for Strequent Uri with {@link ContactsContract#STREQUENT_PHONE_ONLY}, which allows 7004928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * users to obtain part of Data columns. We hard-code {@link Contacts#IS_USER_PROFILE} to NULL, 7014928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * because sContactsProjectionMap specifies a field that doesn't exist in the view behind the 7024928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * query that uses this projection map. 7034928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa **/ 7044928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa private static final ProjectionMap sStrequentPhoneOnlyFrequentProjectionMap 7054928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa = ProjectionMap.builder() 7064928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .addAll(sContactsProjectionMap) 7074928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, DataUsageStatColumns.CONCRETE_TIMES_USED) 7084928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.NUMBER) 7094928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.TYPE) 7104928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.LABEL) 7114928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Contacts.IS_USER_PROFILE, "NULL") 7124928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .build(); 7134928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 714f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 715f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsVCardProjectionMap = ProjectionMap.builder() 716fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen .add(Contacts._ID) 717f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME + " || '.vcf'") 718f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.SIZE, "NULL") 719f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 720f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 721ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 722f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactsProjectionMap = ProjectionMap.builder() 723f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 724f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 725f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 726f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_PRIMARY) 727f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_ALTERNATIVE) 728f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_SOURCE) 729f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME) 730f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME_STYLE) 731f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_PRIMARY) 732f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_ALTERNATIVE) 733f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.TIMES_CONTACTED) 734f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.LAST_TIME_CONTACTED) 735f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CUSTOM_RINGTONE) 736f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SEND_TO_VOICEMAIL) 737f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 738f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.AGGREGATION_MODE) 73924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 740f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 741f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 742f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 743f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 744a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the raw entity view*/ 745f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawEntityProjectionMap = ProjectionMap.builder() 746f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 747f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 748f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.Entity.DATA_ID) 749f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 750f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 75124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 752f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 753f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 754f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 755f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 756f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 757a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the contact entity view*/ 758f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sEntityProjectionMap = ProjectionMap.builder() 759f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity._ID) 760f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.CONTACT_ID) 761f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.RAW_CONTACT_ID) 762f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DATA_ID) 763f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.NAME_RAW_CONTACT_ID) 764f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DELETED) 76524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(Contacts.IS_USER_PROFILE) 766f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 767f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 768f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 769f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 770f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 771f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 772f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 773f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 775f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataProjectionMap = ProjectionMap.builder() 776f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID) 777f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RAW_CONTACT_ID) 778f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CONTACT_ID) 779f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.NAME_RAW_CONTACT_ID) 78024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 781f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 782f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 783f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 784f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 785f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 786f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 787f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 789f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDistinctDataProjectionMap = ProjectionMap.builder() 790f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID, "MIN(" + Data._ID + ")") 791f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 79224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 793f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 794f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 795f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 796f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 797f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 798f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7999261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 800f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sPhoneLookupProjectionMap = ProjectionMap.builder() 801f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup._ID, "contacts_view." + Contacts._ID) 802f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LOOKUP_KEY, "contacts_view." + Contacts.LOOKUP_KEY) 803f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.DISPLAY_NAME, "contacts_view." + Contacts.DISPLAY_NAME) 804f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LAST_TIME_CONTACTED, "contacts_view." + Contacts.LAST_TIME_CONTACTED) 805f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TIMES_CONTACTED, "contacts_view." + Contacts.TIMES_CONTACTED) 806f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.STARRED, "contacts_view." + Contacts.STARRED) 807f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.IN_VISIBLE_GROUP, "contacts_view." + Contacts.IN_VISIBLE_GROUP) 808f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.PHOTO_ID, "contacts_view." + Contacts.PHOTO_ID) 8093d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(PhoneLookup.PHOTO_URI, "contacts_view." + Contacts.PHOTO_URI) 8103d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(PhoneLookup.PHOTO_THUMBNAIL_URI, "contacts_view." + Contacts.PHOTO_THUMBNAIL_URI) 811f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.CUSTOM_RINGTONE, "contacts_view." + Contacts.CUSTOM_RINGTONE) 812f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.HAS_PHONE_NUMBER, "contacts_view." + Contacts.HAS_PHONE_NUMBER) 813f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.SEND_TO_VOICEMAIL, "contacts_view." + Contacts.SEND_TO_VOICEMAIL) 814f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.NUMBER, Phone.NUMBER) 815f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TYPE, Phone.TYPE) 816f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LABEL, Phone.LABEL) 8172530512f639c4979fd7371c7dd25dd67e8118124Bai Tao .add(PhoneLookup.NORMALIZED_NUMBER, Phone.NORMALIZED_NUMBER) 818f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 819f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 820ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 821f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsProjectionMap = ProjectionMap.builder() 822f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups._ID) 823f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_NAME) 824f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_TYPE) 82543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(Groups.DATA_SET) 82643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(Groups.ACCOUNT_TYPE_AND_DATA_SET) 827f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SOURCE_ID) 828f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DIRTY) 829f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.VERSION) 830f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.RES_PACKAGE) 831f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE) 832f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE_RES) 833f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.GROUP_VISIBLE) 834f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYSTEM_ID) 835f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DELETED) 836f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.NOTES) 837f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SHOULD_SYNC) 838f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.FAVORITES) 839f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.AUTO_ADD) 840c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov .add(Groups.GROUP_IS_READ_ONLY) 841f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC1) 842f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC2) 843f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC3) 844f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC4) 845f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 846f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 847ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 848f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsSummaryProjectionMap = ProjectionMap.builder() 849f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sGroupsProjectionMap) 850f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_COUNT, 851f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa "(SELECT COUNT(" + ContactsColumns.CONCRETE_ID + ") FROM " 852f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Tables.CONTACTS_JOIN_RAW_CONTACTS_DATA_FILTERED_BY_GROUPMEMBERSHIP 853f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + ")") 854f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_WITH_PHONES, 855f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa "(SELECT COUNT(" + ContactsColumns.CONCRETE_ID + ") FROM " 856f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Tables.CONTACTS_JOIN_RAW_CONTACTS_DATA_FILTERED_BY_GROUPMEMBERSHIP 857f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " WHERE " + Contacts.HAS_PHONE_NUMBER + ")") 858f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa .build(); 859f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa 860f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa // This is only exposed as hidden API for the contacts app, so we can be very specific in 861f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa // the filtering 862f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa private static final ProjectionMap sGroupsSummaryProjectionMapWithGroupCountPerAccount = 863f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa ProjectionMap.builder() 864f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa .addAll(sGroupsSummaryProjectionMap) 865f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa .add(Groups.SUMMARY_GROUP_COUNT_PER_ACCOUNT, 866f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa "(SELECT COUNT(*) FROM " + Views.GROUPS + " WHERE " 867f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + "(" + Groups.ACCOUNT_NAME + "=" 868f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + GroupsColumns.CONCRETE_ACCOUNT_NAME 869f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " AND " 870f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.ACCOUNT_TYPE + "=" + GroupsColumns.CONCRETE_ACCOUNT_TYPE 871f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " AND " 872f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.DELETED + "=0 AND " 873f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.FAVORITES + "=0 AND " 874f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.AUTO_ADD + "=0" 875f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + ")" 876f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " GROUP BY " 877f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.ACCOUNT_NAME + ", " + Groups.ACCOUNT_TYPE 878f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + ")") 879f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 880f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 881373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 882f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sAggregationExceptionsProjectionMap = ProjectionMap.builder() 883f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id") 884f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.TYPE) 885f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID1) 886f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID2) 887f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 888f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 889eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 890f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSettingsProjectionMap = ProjectionMap.builder() 891f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_NAME) 892f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_TYPE) 893f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro .add(Settings.DATA_SET) 894f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_VISIBLE) 895f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.SHOULD_SYNC) 896f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ANY_UNSYNCED, 897f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 898f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ",(SELECT " 899f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "(CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL" 900f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 901f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE MIN(" + Groups.SHOULD_SYNC + ")" 902f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)" 903f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.GROUPS 904f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 905f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + SettingsColumns.CONCRETE_ACCOUNT_NAME 906f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 907f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + SettingsColumns.CONCRETE_ACCOUNT_TYPE 908f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + " AND ((" + GroupsColumns.CONCRETE_DATA_SET + " IS NULL AND " 909f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + SettingsColumns.CONCRETE_DATA_SET + " IS NULL) OR (" 910f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + GroupsColumns.CONCRETE_DATA_SET + "=" 911f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + SettingsColumns.CONCRETE_DATA_SET + "))))=0" 912f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 913f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE 0" 914f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)") 915f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_COUNT, 916f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 917f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 918f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 919f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 920f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 921f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 922f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_WITH_PHONES, 923f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 924f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 925f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 926f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Contacts.HAS_PHONE_NUMBER 927f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 928f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 929f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 930f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 931f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 93282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 933f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStatusUpdatesProjectionMap = ProjectionMap.builder() 934f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PresenceColumns.RAW_CONTACT_ID) 935f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.DATA_ID, DataColumns.CONCRETE_ID) 936f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_ACCOUNT) 937f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_HANDLE) 938f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PROTOCOL) 939f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 940f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // properly enforce uniqueness of null values 941f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CUSTOM_PROTOCOL, 942f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL + "=''" 943f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN NULL" 944f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END)") 945f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PRESENCE) 946f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CHAT_CAPABILITY) 947f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS) 948f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_TIMESTAMP) 949f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_RES_PACKAGE) 950f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_ICON) 951f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_LABEL) 952f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 953f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 9543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** Contains StreamItems columns */ 9553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final ProjectionMap sStreamItemsProjectionMap = ProjectionMap.builder() 9569b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems._ID) 9579b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.CONTACT_ID) 958af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann .add(StreamItems.CONTACT_LOOKUP_KEY) 9599b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.ACCOUNT_NAME) 9609b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.ACCOUNT_TYPE) 9619b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.DATA_SET) 9623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RAW_CONTACT_ID) 9639b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.RAW_CONTACT_SOURCE_ID) 9643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_PACKAGE) 9653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_ICON) 9663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_LABEL) 9673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.TEXT) 9683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.TIMESTAMP) 9693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.COMMENTS) 9700bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC1) 9710bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC2) 9720bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC3) 9730bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC4) 9743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .build(); 9753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 9763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final ProjectionMap sStreamItemPhotosProjectionMap = ProjectionMap.builder() 9773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos._ID, StreamItemPhotosColumns.CONCRETE_ID) 9783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RAW_CONTACT_ID) 9790bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.RAW_CONTACT_SOURCE_ID, RawContactsColumns.CONCRETE_SOURCE_ID) 9803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos.STREAM_ITEM_ID) 9813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos.SORT_INDEX) 9826802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .add(StreamItemPhotos.PHOTO_FILE_ID) 9836802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .add(StreamItemPhotos.PHOTO_URI, 9846802030a777c0c3ba1dc029c534cca4784260632Dave Santoro "'" + DisplayPhoto.CONTENT_URI + "'||'/'||" + StreamItemPhotos.PHOTO_FILE_ID) 9851dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro .add(PhotoFiles.HEIGHT) 9861dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro .add(PhotoFiles.WIDTH) 9871dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro .add(PhotoFiles.FILESIZE) 9880bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC1) 9890bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC2) 9900bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC3) 9910bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC4) 9923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .build(); 9933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 9941b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 995f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sLiveFoldersProjectionMap = ProjectionMap.builder() 996f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(LiveFolders._ID, Contacts._ID) 997f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(LiveFolders.NAME, Contacts.DISPLAY_NAME) 998f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 999f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // for contacts without a photo 1000f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // .add(LiveFolders.ICON_BITMAP, Photos.DATA) 1001f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 1002f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 1003d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** Contains {@link Directory} columns */ 1004f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDirectoryProjectionMap = ProjectionMap.builder() 1005f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory._ID) 1006f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.PACKAGE_NAME) 1007f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.TYPE_RESOURCE_ID) 1008f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DISPLAY_NAME) 1009f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DIRECTORY_AUTHORITY) 1010f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_TYPE) 1011f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_NAME) 1012f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.EXPORT_SUPPORT) 1013778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov .add(Directory.SHORTCUT_SUPPORT) 1014778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov .add(Directory.PHOTO_SUPPORT) 1015f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 10167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 10179705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // where clause to update the status_updates table 10189705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 10199705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 10209705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 10219705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 10229705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 10232526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private static final String[] EMPTY_STRING_ARRAY = new String[0]; 10242526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 1025bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1026bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Notification ID for failure to import contacts. 1027bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1028bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private static final int LEGACY_IMPORT_FAILED_NOTIFICATION = 1; 102951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 103003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_START_MATCH = "["; 103103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_END_MATCH = "]"; 103203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_ELLIPSIS = "..."; 103303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final int DEFAULT_SNIPPET_ARG_MAX_TOKENS = -10; 103403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 10359a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov private boolean sIsPhoneInitialized; 10369a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov private boolean sIsPhone; 10379a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 1038f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 10391129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 10401129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs2 = new String[2]; 10412526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private ArrayList<String> mSelectionArgs = Lists.newArrayList(); 10422526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 1043f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private Account mAccount; 1044f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 104546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 104646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Stores mapping from type Strings exposed via {@link DataUsageFeedback} to 104746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * type integers in {@link DataUsageStatColumns}. 104846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 104946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final Map<String, Integer> sDataUsageTypeMap; 105046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 10514f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 10524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 1053a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 1054d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 1055d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 1056a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_ID_DATA); 1057a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/entities", CONTACTS_ID_ENTITIES); 10583653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 10593653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 10602d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 10612d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 1062a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_ID_PHOTO); 1063f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/display_photo", 1064f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro CONTACTS_ID_DISPLAY_PHOTO); 10653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/stream_items", 10663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_ID_STREAM_ITEMS); 1067c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter", CONTACTS_FILTER); 10685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 10695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 10702149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/data", CONTACTS_LOOKUP_DATA); 1071bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/photo", 1072bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro CONTACTS_LOOKUP_PHOTO); 10735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 10742149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/data", 10752149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov CONTACTS_LOOKUP_ID_DATA); 1076bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/photo", 1077bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro CONTACTS_LOOKUP_ID_PHOTO); 1078f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/display_photo", 1079f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro CONTACTS_LOOKUP_DISPLAY_PHOTO); 1080f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/display_photo", 1081f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro CONTACTS_LOOKUP_ID_DISPLAY_PHOTO); 1082a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/entities", 1083a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ENTITIES); 1084a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/entities", 1085a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ID_ENTITIES); 10863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/stream_items", 10873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_LOOKUP_STREAM_ITEMS); 10883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/stream_items", 10893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_LOOKUP_ID_STREAM_ITEMS); 1090f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 109142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_multi_vcard/*", 109242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann CONTACTS_AS_MULTI_VCARD); 10935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 1094ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 1095ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 10965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 109745ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa matcher.addURI(ContactsContract.AUTHORITY, "contacts/frequent", CONTACTS_FREQUENT); 10983653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 10995ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 11005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 11015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 1102f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/display_photo", 1103f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro RAW_CONTACTS_ID_DISPLAY_PHOTO); 110446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 11053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/stream_items", 11063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann RAW_CONTACTS_ID_STREAM_ITEMS); 110782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/stream_items/#", 110882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro RAW_CONTACTS_ID_STREAM_ITEMS_ID); 110946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 111046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 1111b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 11124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 11134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 1114ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 111548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 11165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 1117ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 11184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 111948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 11201dac83b8fa58944acfd00f44e717a7dddc659d2dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup", EMAILS_LOOKUP); 11215e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 11225e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 11234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 1124ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 112548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 112646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** "*" is in CSV form with data ids ("123,456,789") */ 112746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa matcher.addURI(ContactsContract.AUTHORITY, "data/usagefeedback/*", DATA_USAGE_FEEDBACK_ID); 11281f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1129ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 1130ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 1131ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 1132ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 113335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 1134b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 1135b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 11365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/" + SyncStateContentProviderHelper.PATH, 11375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROFILE_SYNCSTATE); 11385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, 11395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro "profile/" + SyncStateContentProviderHelper.PATH + "/#", 11405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROFILE_SYNCSTATE_ID); 114135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1142a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 1143b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 1144b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 1145b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 1146b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 11474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1148eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 1149eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 115082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 115182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 11521f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1153c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 1154c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 1155c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 1156c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 11572d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", 1158c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 1159c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 11601b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 11611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 11621b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 11631b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 11641b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 11651b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 11661b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 11671b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 116809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 116909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "provider_status", PROVIDER_STATUS); 1170d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 1171d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories", DIRECTORIES); 1172d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories/#", DIRECTORIES_ID); 11737a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 11747a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "complete_name", COMPLETE_NAME); 117524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 117624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile", PROFILE); 117724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/entities", PROFILE_ENTITIES); 117824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/data", PROFILE_DATA); 117924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/data/#", PROFILE_DATA_ID); 118024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/as_vcard", PROFILE_AS_VCARD); 118124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts", PROFILE_RAW_CONTACTS); 118224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#", 118324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID); 118424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#/data", 118524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID_DATA); 118624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#/entity", 118724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID_ENTITIES); 11885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/status_updates", 11895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROFILE_STATUS_UPDATES); 11903202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contact_entities", 11913202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro PROFILE_RAW_CONTACT_ENTITIES); 119246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 11933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items", STREAM_ITEMS); 11943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/photo", STREAM_ITEMS_PHOTOS); 11953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#", STREAM_ITEMS_ID); 11963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#/photo", STREAM_ITEMS_ID_PHOTOS); 11973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#/photo/#", 11983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann STREAM_ITEMS_ID_PHOTOS_ID); 11993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items_limit", STREAM_ITEMS_LIMIT); 12003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 12015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "display_photo/#", DISPLAY_PHOTO); 1202f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "photo_dimensions", PHOTO_DIMENSIONS); 1203f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 120446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa HashMap<String, Integer> tmpTypeMap = new HashMap<String, Integer>(); 120546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_CALL, DataUsageStatColumns.USAGE_TYPE_INT_CALL); 120646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_LONG_TEXT, 120746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns.USAGE_TYPE_INT_LONG_TEXT); 120846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_SHORT_TEXT, 120946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns.USAGE_TYPE_INT_SHORT_TEXT); 121046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sDataUsageTypeMap = Collections.unmodifiableMap(tmpTypeMap); 121119a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 121219a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 1213d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static class DirectoryInfo { 1214d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String authority; 1215d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountName; 1216d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountType; 1217d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 1218d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 1219d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 1220d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Cached information about contact directories. 1221d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 12224458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private HashMap<String, DirectoryInfo> mDirectoryCache = new HashMap<String, DirectoryInfo>(); 12234458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private boolean mDirectoryCacheValid = false; 1224d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 12253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 122643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * An entry in group id cache. It maps the combination of (account type, account name, data set, 1227ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * and source id) to group row id. 1228ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 1229e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov public static class GroupIdCacheEntry { 1230ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType; 1231ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName; 123243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String dataSet; 1233ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String sourceId; 1234ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov long groupId; 1235ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 1236a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1237e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // We don't need a soft cache for groups - the assumption is that there will only 1238e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // be a small number of contact groups. The cache is keyed off source id. The value 1239e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // is a list of groups with this group id. 1240e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 1241e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov 124224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro /** 1243f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Maximum dimension (height or width) of display photos. Larger images will be scaled 1244f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * to fit. 1245f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 1246f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private int mMaxDisplayPhotoDim; 1247f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1248f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 1249f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Maximum dimension (height or width) of photo thumbnails. 1250f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 1251f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private int mMaxThumbnailPhotoDim; 1252f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 12535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 12545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Sub-provider for handling profile requests against the profile database. 12555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 12565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ProfileProvider mProfileProvider; 1257f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 12584097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1259f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1260315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1261622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1262622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 126372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private ContactDirectoryManager mContactDirectoryManager; 12645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 12665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * The active (thread-local) database. This will be switched between a contacts-specific 12675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * database and a profile-specific database, depending on what the current operation is 12685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * targeted to. 12695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 12705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<SQLiteDatabase> mActiveDb = new ThreadLocal<SQLiteDatabase>(); 12715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // This variable keeps track of whether the current operation is intended for the profile DB. 12735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<Boolean> mInProfileMode = new ThreadLocal<Boolean>(); 12745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Whether we're currently in the process of applying a batch of operations. 12765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<Boolean> mApplyingBatch = new ThreadLocal<Boolean>(); 12775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Separate data row handler instances for contact data and profile data. 12795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private HashMap<String, DataRowHandler> mDataRowHandlers; 12805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private HashMap<String, DataRowHandler> mProfileDataRowHandlers; 12815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Depending on whether the action being performed is for the profile, we will use one of two 12835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // database helper instances. 12845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<ContactsDatabaseHelper> mDbHelper = 12855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ThreadLocal<ContactsDatabaseHelper>(); 12865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ContactsDatabaseHelper mContactsHelper; 12875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ProfileDatabaseHelper mProfileHelper; 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 aggregator instances. 12915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<ContactAggregator> mAggregator = new ThreadLocal<ContactAggregator>(); 1292622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 12935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ContactAggregator mProfileAggregator; 12945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Depending on whether the action being performed is for the profile or not, we will use one of 12965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // two photo store instances (with their files stored in separate subdirectories). 12975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<PhotoStore> mPhotoStore = new ThreadLocal<PhotoStore>(); 12985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private PhotoStore mContactsPhotoStore; 12995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private PhotoStore mProfilePhotoStore; 13005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 13015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // The active transaction context will switch depending on the operation being performed. 13025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Both transaction contexts will be cleared out when a batch transaction is started, and 13035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // each will be processed separately when a batch transaction completes. 13045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private TransactionContext mContactTransactionContext = new TransactionContext(false); 13055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private TransactionContext mProfileTransactionContext = new TransactionContext(true); 13065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<TransactionContext> mTransactionContext = 13075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ThreadLocal<TransactionContext>(); 13085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 13095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // This database reference will only be referenced when a batch operation is in progress 13105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // that includes profile DB operations. It is used to create and handle a separate transaction 13115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // around that batch. Outside of such a batch operation, this will be null. 13125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<SQLiteDatabase> mProfileDbForBatch = 13135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ThreadLocal<SQLiteDatabase>(); 13145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 13155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // This flag is set during a batch operation that involves the profile DB to indicate that 13165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // errors occurred during processing of one of the profile operations. 13175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<Boolean> mProfileErrorsInBatch = new ThreadLocal<Boolean>(); 13185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 1319f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1320a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1321d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov private CommonNicknameCache mCommonNicknameCache; 1322f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private SearchIndexManager mSearchIndexManager; 1323a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 132420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 132573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov private HashMap<String, Boolean> mAccountWritability = Maps.newHashMap(); 132620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 132709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private int mProviderStatus = ProviderStatus.STATUS_NORMAL; 13283826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private boolean mProviderStatusUpdateNeeded; 132909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private long mEstimatedStorageRequirement = 0; 133015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private volatile CountDownLatch mReadAccessLatch; 133115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private volatile CountDownLatch mWriteAccessLatch; 133215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private boolean mAccountUpdateListenerRegistered; 1333bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private boolean mOkToOpenAccess = true; 133473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 13351a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 13361a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 133781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 133881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 13394cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao private Locale mCurrentLocale; 13403826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private int mContactsAccountCount; 1341d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 1342bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private HandlerThread mBackgroundThread; 1343bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private Handler mBackgroundHandler; 1344bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1345f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private long mLastPhotoCleanup = 0; 1346f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 13474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 13484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1349663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) { 1350663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki Log.d(Constants.PERFORMANCE_TAG, "ContactsProvider2.onCreate start"); 1351663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } 1352de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 1353ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov try { 1354ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return initialize(); 1355ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } catch (RuntimeException e) { 1356ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov Log.e(TAG, "Cannot start provider", e); 1357ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return false; 1358663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } finally { 1359663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) { 1360663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki Log.d(Constants.PERFORMANCE_TAG, "ContactsProvider2.onCreate finish"); 1361663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } 1362ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 1363ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 136435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1365ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov private boolean initialize() { 136615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov StrictMode.setThreadPolicy( 136715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()); 136815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 13693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Resources resources = getContext().getResources(); 1370f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mMaxDisplayPhotoDim = resources.getInteger( 1371f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro R.integer.config_max_display_photo_dim); 1372f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mMaxThumbnailPhotoDim = resources.getInteger( 1373f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro R.integer.config_max_thumbnail_photo_dim); 13743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 13755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper = (ContactsDatabaseHelper) getDatabaseHelper(); 13765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.set(mContactsHelper); 137772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mContactDirectoryManager = new ContactDirectoryManager(this); 1378a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 137965ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov 1380bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // The provider is closed for business until fully initialized 138115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch = new CountDownLatch(1); 138215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch = new CountDownLatch(1); 138372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 1384bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundThread = new HandlerThread("ContactsProviderWorker", 1385bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov Process.THREAD_PRIORITY_BACKGROUND); 1386bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundThread.start(); 1387bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler = new Handler(mBackgroundThread.getLooper()) { 1388bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 1389bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void handleMessage(Message msg) { 1390bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov performBackgroundTask(msg.what, msg.obj); 1391bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1392bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov }; 13932a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov 13945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Set up the sub-provider for handling profiles. 13955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileProvider = getProfileProvider(); 13965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ProviderInfo profileInfo = new ProviderInfo(); 13975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileInfo.readPermission = "android.permission.READ_PROFILE"; 13985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileInfo.writePermission = "android.permission.WRITE_PROFILE"; 13995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileProvider.attachInfo(getContext(), profileInfo); 14005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper = (ProfileDatabaseHelper) mProfileProvider.getDatabaseHelper(); 14015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 140215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_INITIALIZE); 1403bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS); 1404bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS); 1405bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_LOCALE); 1406bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM); 140705e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_SEARCH_INDEX); 1408bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_PROVIDER_STATUS); 140915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_OPEN_WRITE_ACCESS); 1410f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS); 14113826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 141249d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov return true; 14134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 14144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1415767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov /** 141651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * (Re)allocates all locale-sensitive structures. 141751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 141804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov private void initForDefaultLocale() { 141915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Context context = getContext(); 14205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mLegacyApiSupport = new LegacyApiSupport(context, mContactsHelper, this, 14215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mGlobalSearchSupport); 14224cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mCurrentLocale = getLocale(); 14235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mNameSplitter = mContactsHelper.createNameSplitter(); 14244cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 14254cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mPostalSplitter = new PostalSplitter(mCurrentLocale); 14265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mCommonNicknameCache = new CommonNicknameCache(mContactsHelper.getReadableDatabase()); 1427cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao ContactLocaleUtils.getIntance().setLocale(mCurrentLocale); 14285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactAggregator = new ContactAggregator(this, mContactsHelper, 142915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov createPhotoPriorityResolver(context), mNameSplitter, mCommonNicknameCache); 14305b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 14315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileAggregator = new ProfileAggregator(this, mProfileHelper, 14325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro createPhotoPriorityResolver(context), mNameSplitter, mCommonNicknameCache); 14335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1434f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSearchIndexManager = new SearchIndexManager(this); 14355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 14365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsPhotoStore = new PhotoStore(getContext().getFilesDir(), mContactsHelper); 14375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfilePhotoStore = new PhotoStore(new File(getContext().getFilesDir(), "profile"), 14385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper); 14395b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 1440bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 14415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro initDataRowHandlers(mDataRowHandlers, mContactsHelper, mContactAggregator, 14425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsPhotoStore); 14435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDataRowHandlers = new HashMap<String, DataRowHandler>(); 14445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro initDataRowHandlers(mProfileDataRowHandlers, mProfileHelper, mProfileAggregator, 14455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfilePhotoStore); 14465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 14475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Set initial thread-local state variables for the Contacts DB. 14485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 14495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 1450bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 14515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private void initDataRowHandlers(Map<String, DataRowHandler> handlerMap, 14525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ContactsDatabaseHelper dbHelper, ContactAggregator contactAggregator, 14535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PhotoStore photoStore) { 14545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Context context = getContext(); 14555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Email.CONTENT_ITEM_TYPE, 14565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForEmail(context, dbHelper, contactAggregator)); 14575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Im.CONTENT_ITEM_TYPE, 14585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForIm(context, dbHelper, contactAggregator)); 14595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Organization.CONTENT_ITEM_TYPE, 14605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForOrganization(context, dbHelper, contactAggregator)); 14615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Phone.CONTENT_ITEM_TYPE, 14625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForPhoneNumber(context, dbHelper, contactAggregator)); 14635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Nickname.CONTENT_ITEM_TYPE, 14645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForNickname(context, dbHelper, contactAggregator)); 14655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(StructuredName.CONTENT_ITEM_TYPE, 14665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForStructuredName(context, dbHelper, contactAggregator, 1467bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mNameSplitter, mNameLookupBuilder)); 14685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(StructuredPostal.CONTENT_ITEM_TYPE, 14695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForStructuredPostal(context, dbHelper, contactAggregator, 1470bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mPostalSplitter)); 14715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(GroupMembership.CONTENT_ITEM_TYPE, 14725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForGroupMembership(context, dbHelper, contactAggregator, 1473bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mGroupIdCache)); 14745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Photo.CONTENT_ITEM_TYPE, 14755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForPhoto(context, dbHelper, contactAggregator, photoStore)); 14765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Note.CONTENT_ITEM_TYPE, 14775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForNote(context, dbHelper, contactAggregator)); 1478bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1479bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1480bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /** 1481bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Visible for testing. 1482bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov */ 1483bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /* package */ PhotoPriorityResolver createPhotoPriorityResolver(Context context) { 1484bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return new PhotoPriorityResolver(context); 1485bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1486bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1487bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void scheduleBackgroundTask(int task) { 1488bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler.sendEmptyMessage(task); 1489bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1490bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1491bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void scheduleBackgroundTask(int task, Object arg) { 1492bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler.sendMessage(mBackgroundHandler.obtainMessage(task, arg)); 1493bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1494bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1495bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void performBackgroundTask(int task, Object arg) { 1496bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov switch (task) { 149715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case BACKGROUND_TASK_INITIALIZE: { 149815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov initForDefaultLocale(); 149915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch.countDown(); 150015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch = null; 150115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov break; 150215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 150315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 150415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case BACKGROUND_TASK_OPEN_WRITE_ACCESS: { 1505bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (mOkToOpenAccess) { 150615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch.countDown(); 150715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch = null; 1508bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1509bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1510bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1511bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1512bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS: { 1513bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1514bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov importLegacyContactsInBackground(); 1515bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1516bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1517bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1518bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1519bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_ACCOUNTS: { 152015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Context context = getContext(); 152115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (!mAccountUpdateListenerRegistered) { 152215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov AccountManager.get(context).addOnAccountsUpdatedListener(this, null, false); 152315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mAccountUpdateListenerRegistered = true; 152415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 152515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 15265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Update the accounts for both the contacts and profile DBs. 152715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Account[] accounts = AccountManager.get(context).getAccounts(); 15285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 1529bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov boolean accountsChanged = updateAccountsInBackground(accounts); 15305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 15315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro accountsChanged |= updateAccountsInBackground(accounts); 15325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 1533bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateContactsAccountCount(accounts); 1534bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateDirectoriesInBackground(accountsChanged); 1535bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1536bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1537bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1538bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_LOCALE: { 1539bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateLocaleInBackground(); 1540bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1541bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1542bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1543fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov case BACKGROUND_TASK_CHANGE_LOCALE: { 1544fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov changeLocaleInBackground(); 1545fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov break; 1546fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1547fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1548bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM: { 1549bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (isAggregationUpgradeNeeded()) { 1550bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov upgradeAggregationAlgorithmInBackground(); 1551bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1552bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1553bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1554bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 155505e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_SEARCH_INDEX: { 155605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov updateSearchIndexInBackground(); 155705e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov break; 155805e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 155905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 1560bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_PROVIDER_STATUS: { 1561bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateProviderStatus(); 1562bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1563bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1564bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1565bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_DIRECTORIES: { 1566bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (arg != null) { 1567bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.onPackageChanged((String) arg); 1568bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1569bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1570bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1571f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1572f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case BACKGROUND_TASK_CLEANUP_PHOTOS: { 1573f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Check rate limit. 1574f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long now = System.currentTimeMillis(); 1575f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (now - mLastPhotoCleanup > PHOTO_CLEANUP_RATE_LIMIT) { 1576f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mLastPhotoCleanup = now; 15775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 15785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Clean up photo stores for both contacts and profiles. 15795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 15805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro cleanupPhotoStore(); 15815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 1582f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro cleanupPhotoStore(); 1583f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro break; 1584f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1585f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1586bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 15874cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 15884cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao 158953fac8f99f3884c372c907a76766d27fa9e1d95fDmitri Plotnikov public void onLocaleChanged() { 15903826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL 15913826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov && mProviderStatus != ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) { 15924f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov return; 15934f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov } 15944f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov 1595fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_CHANGE_LOCALE); 15964cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 159751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 159851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov /** 159951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * Verifies that the contacts database is properly configured for the current locale. 160051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * If not, changes the database locale to the current locale using an asynchronous task. 160151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * This needs to be done asynchronously because the process involves rebuilding 160251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * large data structures (name lookup, sort keys), which can take minutes on 160351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * a large set of contacts. 160451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 1605bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void updateLocaleInBackground() { 1606f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 1607f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // The process is already running - postpone the change 1608f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov if (mProviderStatus == ProviderStatus.STATUS_CHANGING_LOCALE) { 1609f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov return; 1610f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov } 1611f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 161251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 161351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final String providerLocale = prefs.getString(PREF_LOCALE, null); 161451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final Locale currentLocale = mCurrentLocale; 161551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov if (currentLocale.toString().equals(providerLocale)) { 161651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return; 161751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 161851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 161951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov int providerStatus = mProviderStatus; 162051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_CHANGING_LOCALE); 16215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setLocale(this, currentLocale); 16225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper.setLocale(this, currentLocale); 1623bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, currentLocale.toString()).apply(); 1624bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov setProviderStatus(providerStatus); 1625bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 162651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 1627fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov /** 1628fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov * Reinitializes the provider for a new locale. 1629fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov */ 1630fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov private void changeLocaleInBackground() { 1631fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // Re-initializing the provider without stopping it. 1632fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // Locking the database will prevent inserts/updates/deletes from 1633fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // running at the same time, but queries may still be running 1634fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // on other threads. Those queries may return inconsistent results. 16355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mContactsHelper.getWritableDatabase(); 16365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase profileDb = mProfileHelper.getWritableDatabase(); 1637fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.beginTransaction(); 16385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.beginTransaction(); 1639fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov try { 1640fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov initForDefaultLocale(); 1641fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.setTransactionSuccessful(); 16425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.setTransactionSuccessful(); 1643fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } finally { 1644fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.endTransaction(); 16455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.endTransaction(); 1646fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1647fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1648fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov updateLocaleInBackground(); 1649fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1650fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 165105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov protected void updateSearchIndexInBackground() { 165205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov mSearchIndexManager.updateIndex(); 165305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 165405e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 1655bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void updateDirectoriesInBackground(boolean rescan) { 1656bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.scanAllPackages(rescan); 165751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 165851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 16593826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private void updateProviderStatus() { 16603826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL 16613826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov && mProviderStatus != ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) { 16623826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return; 16633826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 16643826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 16653e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson // No accounts/no contacts status is true if there are no account and 16665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // there are no contacts or one profile contact 16673e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson if (mContactsAccountCount == 0) { 16685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactsNum = DatabaseUtils.queryNumEntries(mContactsHelper.getReadableDatabase(), 16693e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson Tables.CONTACTS, null); 16705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long profileNum = DatabaseUtils.queryNumEntries(mProfileHelper.getReadableDatabase(), 16715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Tables.CONTACTS, null); 16725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 16735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // TODO: Different status if there is a profile but no contacts? 16745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (contactsNum == 0 && profileNum <= 1) { 16753e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson setProviderStatus(ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS); 16763e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson } else { 16773e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson setProviderStatus(ProviderStatus.STATUS_NORMAL); 16783e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson } 16793826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } else { 16803826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 16813826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 16823826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 16833826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 168431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1685f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro protected void cleanupPhotoStore() { 16865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mDbHelper.get().getWritableDatabase(); 16876802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 16886802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Assemble the set of photo store file IDs that are in use, and send those to the photo 1689f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // store. Any photos that aren't in that set will be deleted, and any photos that no 1690f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // longer exist in the photo store will be returned for us to clear out in the DB. 16917cf50494501938f175d288077145acf49da8f171Daniel Lehmann long photoMimeTypeId = mDbHelper.get().getMimeTypeId(Photo.CONTENT_ITEM_TYPE); 16926802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Cursor c = db.query(Views.DATA, new String[]{Data._ID, Photo.PHOTO_FILE_ID}, 16937cf50494501938f175d288077145acf49da8f171Daniel Lehmann DataColumns.MIMETYPE_ID + "=" + photoMimeTypeId + " AND " 1694f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro + Photo.PHOTO_FILE_ID + " IS NOT NULL", null, null, null, null); 16956802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Set<Long> usedPhotoFileIds = Sets.newHashSet(); 16966802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Map<Long, Long> photoFileIdToDataId = Maps.newHashMap(); 1697f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 1698f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro while (c.moveToNext()) { 16996802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long dataId = c.getLong(0); 17006802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long photoFileId = c.getLong(1); 17016802030a777c0c3ba1dc029c534cca4784260632Dave Santoro usedPhotoFileIds.add(photoFileId); 17026802030a777c0c3ba1dc029c534cca4784260632Dave Santoro photoFileIdToDataId.put(photoFileId, dataId); 17036802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 17046802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } finally { 17056802030a777c0c3ba1dc029c534cca4784260632Dave Santoro c.close(); 17066802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 17076802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 17086802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Also query for all social stream item photos. 1709c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro c = db.query(Tables.STREAM_ITEM_PHOTOS + " JOIN " + Tables.STREAM_ITEMS 1710c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro + " ON " + StreamItemPhotos.STREAM_ITEM_ID + "=" + StreamItemsColumns.CONCRETE_ID 1711c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro + " JOIN " + Tables.RAW_CONTACTS 1712c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro + " ON " + StreamItems.RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID, 17136802030a777c0c3ba1dc029c534cca4784260632Dave Santoro new String[]{ 1714c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro StreamItemPhotosColumns.CONCRETE_ID, 1715c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID, 1716c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro StreamItemPhotos.PHOTO_FILE_ID, 1717c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro RawContacts.ACCOUNT_TYPE, 1718c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro RawContacts.ACCOUNT_NAME 17196802030a777c0c3ba1dc029c534cca4784260632Dave Santoro }, 17206802030a777c0c3ba1dc029c534cca4784260632Dave Santoro null, null, null, null, null); 17216802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Map<Long, Long> photoFileIdToStreamItemPhotoId = Maps.newHashMap(); 17226802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Map<Long, Long> streamItemPhotoIdToStreamItemId = Maps.newHashMap(); 1723c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro Map<Long, Account> streamItemPhotoIdToAccount = Maps.newHashMap(); 17246802030a777c0c3ba1dc029c534cca4784260632Dave Santoro try { 17256802030a777c0c3ba1dc029c534cca4784260632Dave Santoro while (c.moveToNext()) { 17266802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemPhotoId = c.getLong(0); 17276802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemId = c.getLong(1); 17286802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long photoFileId = c.getLong(2); 1729c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro String accountType = c.getString(3); 1730c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro String accountName = c.getString(4); 17316802030a777c0c3ba1dc029c534cca4784260632Dave Santoro usedPhotoFileIds.add(photoFileId); 17326802030a777c0c3ba1dc029c534cca4784260632Dave Santoro photoFileIdToStreamItemPhotoId.put(photoFileId, streamItemPhotoId); 17336802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemPhotoIdToStreamItemId.put(streamItemPhotoId, streamItemId); 1734c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro Account account = new Account(accountName, accountType); 1735c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro streamItemPhotoIdToAccount.put(photoFileId, account); 1736f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1737f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 1738f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 1739f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1740f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1741f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Run the photo store cleanup. 17425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> missingPhotoIds = mPhotoStore.get().cleanup(usedPhotoFileIds); 1743f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1744f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // If any of the keys we're using no longer exist, clean them up. 17456802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (!missingPhotoIds.isEmpty()) { 1746f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ArrayList<ContentProviderOperation> ops = Lists.newArrayList(); 17476802030a777c0c3ba1dc029c534cca4784260632Dave Santoro for (long missingPhotoId : missingPhotoIds) { 17486802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoFileIdToDataId.containsKey(missingPhotoId)) { 17496802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long dataId = photoFileIdToDataId.get(missingPhotoId); 1750f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ContentValues updateValues = new ContentValues(); 1751f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.putNull(Photo.PHOTO_FILE_ID); 1752f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ops.add(ContentProviderOperation.newUpdate( 17536802030a777c0c3ba1dc029c534cca4784260632Dave Santoro ContentUris.withAppendedId(Data.CONTENT_URI, dataId)) 1754f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .withValues(updateValues).build()); 1755f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 17566802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoFileIdToStreamItemPhotoId.containsKey(missingPhotoId)) { 17576802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // For missing photos that were in stream item photos, just delete the stream 17586802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // item photo. 17596802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemPhotoId = photoFileIdToStreamItemPhotoId.get(missingPhotoId); 17606802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemId = streamItemPhotoIdToStreamItemId.get(streamItemPhotoId); 1761c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro Account account = streamItemPhotoIdToAccount.get(missingPhotoId); 17626802030a777c0c3ba1dc029c534cca4784260632Dave Santoro ops.add(ContentProviderOperation.newDelete( 17636802030a777c0c3ba1dc029c534cca4784260632Dave Santoro StreamItems.CONTENT_URI.buildUpon() 17646802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .appendPath(String.valueOf(streamItemId)) 17656802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .appendPath(StreamItems.StreamItemPhotos.CONTENT_DIRECTORY) 17666802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .appendPath(String.valueOf(streamItemPhotoId)) 1767c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro .appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name) 1768c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro .appendQueryParameter(RawContacts.ACCOUNT_TYPE, account.type) 17696802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .build()).build()); 17706802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 1771f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1772f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 1773f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro applyBatch(ops); 1774f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } catch (OperationApplicationException oae) { 1775f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Not a fatal problem (and we'll try again on the next cleanup). 1776f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Log.e(TAG, "Failed to clean up outdated photo references", oae); 1777f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1778f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1779f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1780f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1781f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /* Visible for testing */ 1782de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 1783b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 1784b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 178531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 178631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 17875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public ProfileProvider getProfileProvider() { 17885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return new ProfileProvider(this); 17895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 17905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 1791524913c66ce75ca8dec127ac88e3bc2249c246d9Dave Santoro @VisibleForTesting 1792f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /* package */ PhotoStore getPhotoStore() { 17935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mContactsPhotoStore; 1794f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1795f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 179687614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro /* package */ int getMaxDisplayPhotoDim() { 179787614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro return mMaxDisplayPhotoDim; 179887614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro } 179987614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro 180087614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro /* package */ int getMaxThumbnailPhotoDim() { 180187614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro return mMaxThumbnailPhotoDim; 180287614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro } 180387614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro 1804013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1805013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1806013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1807013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 18085df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov /* package */ NameLookupBuilder getNameLookupBuilder() { 18095df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov return mNameLookupBuilder; 18105df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov } 18115df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov 18125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov /* Visible for testing */ 1813ed78fd6df5e9f3a2d572162e5d374d1f4a625bddDmitri Plotnikov public ContactDirectoryManager getContactDirectoryManagerForTest() { 181472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov return mContactDirectoryManager; 181572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 181672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 181772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /* Visible for testing */ 18185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov protected Locale getLocale() { 18195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov return Locale.getDefault(); 18205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 18215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 18225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean applyingBatch() { 18235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Boolean applyingBatch = mApplyingBatch.get(); 18245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return applyingBatch != null && applyingBatch; 18255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 18265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 18275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean inProfileMode() { 18285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Boolean profileMode = mInProfileMode.get(); 18295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return profileMode != null && profileMode; 18305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 18315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 18323d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 18335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int version = Integer.parseInt( 18345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.getProperty(PROPERTY_CONTACTS_IMPORTED, "0")); 1835b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return version < PROPERTY_CONTACTS_IMPORT_VERSION; 18363d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18373d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1838568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1839568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1840568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1841568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1842568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1843bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Imports legacy contacts as a background task. 1844568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1845bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private void importLegacyContactsInBackground() { 1846bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Importing legacy contacts"); 1847bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADING); 1848568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1849bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 18505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setLocale(this, mCurrentLocale); 1851bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, mCurrentLocale.toString()).commit(); 1852568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1853bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1854bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (importLegacyContacts(importer)) { 1855bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov onLegacyContactImportSuccess(); 1856bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } else { 1857bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov onLegacyContactImportFailure(); 1858bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1859568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1860568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1861bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1862bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Unlocks the provider and declares that the import process is complete. 1863bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1864bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportSuccess() { 1865bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 1866bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)getContext().getSystemService(Context.NOTIFICATION_SERVICE); 1867bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.cancel(LEGACY_IMPORT_FAILED_NOTIFICATION); 1868bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1869b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov // Store a property in the database indicating that the conversion process succeeded 18705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setProperty(PROPERTY_CONTACTS_IMPORTED, 1871b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov String.valueOf(PROPERTY_CONTACTS_IMPORT_VERSION)); 1872bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 1873bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Completed import of legacy contacts"); 1874bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1875bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1876bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1877bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Announces the provider status and keeps the provider locked. 1878bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1879bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportFailure() { 1880bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Context context = getContext(); 1881bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 1882bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); 1883bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1884bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // Show a notification 1885bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Notification n = new Notification(android.R.drawable.stat_notify_error, 1886bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_ticker), 1887bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov System.currentTimeMillis()); 1888bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.setLatestEventInfo(context, 1889bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_title), 1890bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_text), 1891bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov PendingIntent.getActivity(context, 0, new Intent(Intents.UI.LIST_DEFAULT), 0)); 1892bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; 1893bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1894bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.notify(LEGACY_IMPORT_FAILED_NOTIFICATION, n); 1895bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1896bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADE_OUT_OF_MEMORY); 1897bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Failed to import legacy contacts"); 1898bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1899bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // Do not let any database changes until this issue is resolved. 1900bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mOkToOpenAccess = false; 19013d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 19023d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 19033d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1904568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 19050e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 19063d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 19073d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 1908bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (importer.importContacts()) { 1909bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1910bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // TODO aggregate all newly added raw contacts 1911bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mContactAggregator.setEnabled(aggregatorEnabled); 1912bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return true; 1913bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 19143d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 19153d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 19163d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1917bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mEstimatedStorageRequirement = importer.getEstimatedStorageRequirement(); 1918bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return false; 19193d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 19203d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1921a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1922a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1923a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1924a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 19255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.wipeData(); 19265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper.wipeData(); 19275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsPhotoStore.clear(); 19285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfilePhotoStore.clear(); 19293826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatus = ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS; 1930a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1931a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1932568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 193315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov * During intialization, this content provider will 1934568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1935568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1936568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1937568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1938568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 193915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private void waitForAccess(CountDownLatch latch) { 194015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (latch == null) { 194115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return; 194215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 194315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 194415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov while (true) { 194515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov try { 194615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov latch.await(); 194715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return; 194815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } catch (InterruptedException e) { 194915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Thread.currentThread().interrupt(); 1950ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1951568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1952568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1953568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 19545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 19555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Determines whether the given URI should be directed to the profile 19565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * database rather than the contacts database. This is true under either 19575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * of three conditions: 19585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * 1. The URI itself is specifically for the profile. 19595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * 2. The URI contains ID references that are in the profile ID-space. 19605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * 3. The URI contains lookup key references that match the special profile lookup key. 19615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param uri The URI to examine. 19625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @return Whether to direct the DB operation to the profile database. 19635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 19645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean mapsToProfileDb(Uri uri) { 19655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return sUriMatcher.mapsToProfile(uri); 19665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 19685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 19695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Determines whether the given URI with the given values being inserted 19705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * should be directed to the profile database rather than the contacts 19715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * database. This is true if the URI already maps to the profile DB from 19725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * a call to {@link #mapsToProfileDb} or if the URI matches a URI that 19735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * specifies parent IDs via the ContentValues, and the given ContentValues 19745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * contains an ID in the profile ID-space. 19755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param uri The URI to examine. 19765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param values The values being inserted. 19775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @return Whether to direct the DB insert to the profile database. 19785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 19795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean mapsToProfileDbWithInsertedValues(Uri uri, ContentValues values) { 19805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 19815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return true; 19825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int match = sUriMatcher.match(uri); 19845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (INSERT_URI_ID_VALUE_MAP.containsKey(match)) { 19855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String idField = INSERT_URI_ID_VALUE_MAP.get(match); 19865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (values.containsKey(idField)) { 19875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long id = values.getAsLong(idField); 19885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (ContactsContract.isProfileId(id)) { 19895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return true; 19905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return false; 19945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 19965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 19975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Switches the provider's thread-local context variables to prepare for performing 19985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * a profile operation. 19995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 20005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private void switchToProfileMode() { 20015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.set(mProfileHelper); 20025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.set(mProfileTransactionContext); 20035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.set(mProfileAggregator); 20045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mPhotoStore.set(mProfilePhotoStore); 20055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mInProfileMode.set(true); 20065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 20075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // If we're in batch mode and don't yet have a database set up for our transaction, 20085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // get one and start a transaction now. 20095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (applyingBatch() && mProfileDbForBatch.get() == null) { 20105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase profileDb = mProfileHelper.getWritableDatabase(); 20115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.beginTransactionWithListener(this); 20125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDbForBatch.set(profileDb); 20135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 20165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 20175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Switches the provider's thread-local context variables to prepare for performing 20185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * a contacts operation. 20195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 20205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private void switchToContactMode() { 20215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.set(mContactsHelper); 20225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.set(mContactTransactionContext); 20235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.set(mContactAggregator); 20245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mPhotoStore.set(mContactsPhotoStore); 20255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mInProfileMode.set(false); 20265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 20275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // If not in batch mode, clear out the active database - it will be set to the default 20285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // instance from SQLiteContentProvider if necessary. 20295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (!applyingBatch()) { 20305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(null); 20315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 2034568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2035568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 203615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 20375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDbWithInsertedValues(uri, values)) { 2038072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro if (applyingBatch()) { 2039072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2040072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return mProfileProvider.insert(uri, values); 2041072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } else { 2042072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Start a contacts DB transaction to maintain provider synchronization. 2043072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro SQLiteDatabase contactsDb = mContactsHelper.getWritableDatabase(); 2044072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.beginTransactionWithListener(this); 2045072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro Uri result = null; 2046072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro try { 2047072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Now switch to profile mode and proceed with the insert using its provider. 2048072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2049072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro result = mProfileProvider.insert(uri, values); 2050072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2051072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.setTransactionSuccessful(); 2052072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } finally { 2053072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Finish the contacts transaction, allowing other provider operations to 2054072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // proceed. 2055072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.endTransaction(); 2056072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 2057072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return result; 2058072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 20595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 20605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 20615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return super.insert(uri, values); 20625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 2063568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2064568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2065568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2066568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 206715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (mWriteAccessLatch != null) { 2068bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // We are stuck trying to upgrade contacts db. The only update request 2069bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // allowed in this case is an update of provider status, which will trigger 2070bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // an attempt to upgrade contacts again. 2071bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov int match = sUriMatcher.match(uri); 2072bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (match == PROVIDER_STATUS) { 2073bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Integer newStatus = values.getAsInteger(ProviderStatus.STATUS); 2074bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (newStatus != null && newStatus == ProviderStatus.STATUS_UPGRADING) { 2075bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS); 2076bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 1; 2077bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 2078bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 0; 2079bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2080bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2081bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 208215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 20835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 2084072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro if (applyingBatch()) { 2085072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2086072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return mProfileProvider.update(uri, values, selection, selectionArgs); 2087072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } else { 2088072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Start a contacts DB transaction to maintain provider synchronization. 2089072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro SQLiteDatabase contactsDb = mContactsHelper.getWritableDatabase(); 2090072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.beginTransactionWithListener(this); 2091072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro int result = 0; 2092072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro try { 2093072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Now switch to profile mode and proceed with the update using its provider. 2094072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2095072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro result = mProfileProvider.update(uri, values, selection, selectionArgs); 2096072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2097072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.setTransactionSuccessful(); 2098072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } finally { 2099072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Finish the contacts transaction, allowing other provider operations to 2100072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // proceed. 2101072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.endTransaction(); 2102072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 2103072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return result; 2104072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 21055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 21065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 21075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return super.update(uri, values, selection, selectionArgs); 21085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 2109568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2110568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2111568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2112568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 211315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 21145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 2115072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro if (applyingBatch()) { 2116072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2117072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return mProfileProvider.delete(uri, selection, selectionArgs); 2118072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } else { 2119072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Start a contacts DB transaction to maintain provider synchronization. 2120072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro SQLiteDatabase contactsDb = mContactsHelper.getWritableDatabase(); 2121072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.beginTransactionWithListener(this); 2122072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro int result = 0; 2123072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro try { 2124072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Now switch to profile mode and proceed with the delete using its provider. 2125072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2126072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro result = mProfileProvider.delete(uri, selection, selectionArgs); 2127072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2128072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.setTransactionSuccessful(); 2129072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } finally { 2130072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Finish the contacts transaction, allowing other provider operations to 2131072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // proceed. 2132072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.endTransaction(); 2133072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 2134072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return result; 2135072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 21365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 21375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 21385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return super.delete(uri, selection, selectionArgs); 21395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 21425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 21435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Replaces the current (thread-local) database to use for the operation with the given one. 21445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param db The database to use. 21455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 21465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /* package */ void substituteDb(SQLiteDatabase db) { 21475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(db); 2148568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2149568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2150568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2151568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 2152568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 215315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 21545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ContentProviderResult[] results = null; 21555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro try { 2156d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro mApplyingBatch.set(true); 21575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro results = super.applyBatch(operations); 21585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } finally { 2159d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro mApplyingBatch.set(false); 21605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mProfileDbForBatch.get() != null) { 21615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // A profile operation was involved, so clean up its transaction. 21625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro boolean profileErrors = mProfileErrorsInBatch.get() != null 21635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro && mProfileErrorsInBatch.get(); 21645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (!profileErrors) { 21655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDbForBatch.get().setTransactionSuccessful(); 21665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDbForBatch.get().endTransaction(); 21685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDbForBatch.set(null); 21695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileErrorsInBatch.set(false); 21705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return results; 2173568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2174568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 21754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 21767b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov public int bulkInsert(Uri uri, ContentValues[] values) { 21777b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov waitForAccess(mWriteAccessLatch); 2178720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro 2179720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro // Note: This duplicates much of the logic in the superclass, but handles toggling 2180720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro // into profile mode if necessary. 2181720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro int numValues = values.length; 2182720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro boolean notifyChange = false; 2183720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro SQLiteDatabase profileDb = null; 2184072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2185072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Always get a contacts DB and start a transaction on it, to maintain provider 2186072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // synchronization. 21878d55bbc171bea632e960e0e5a88557cef5e66d92Dave Santoro mDb = mContactsHelper.getWritableDatabase(); 21888d55bbc171bea632e960e0e5a88557cef5e66d92Dave Santoro mDb.beginTransactionWithListener(this); 2189720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro try { 2190720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro for (int i = 0; i < numValues; i++) { 2191720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro Uri result; 2192720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (mapsToProfileDbWithInsertedValues(uri, values[i])) { 2193720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro switchToProfileMode(); 2194072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2195072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Initialize the profile DB and start a profile transaction if we haven't 2196072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // already done so. 2197720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (profileDb == null) { 2198720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro profileDb = mProfileHelper.getWritableDatabase(); 2199720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro profileDb.beginTransactionWithListener(this); 2200720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2201720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro result = mProfileProvider.insertInTransaction(uri, values[i]); 2202720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } else { 2203720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro switchToContactMode(); 2204720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro result = insertInTransaction(uri, values[i]); 2205720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2206720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (result != null) { 2207720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro notifyChange = true; 2208720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2209720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro boolean savedNotifyChange = notifyChange; 2210720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro mActiveDb.get().yieldIfContendedSafely(); 2211720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro notifyChange = savedNotifyChange; 2212720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 22138d55bbc171bea632e960e0e5a88557cef5e66d92Dave Santoro mDb.setTransactionSuccessful(); 2214720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (profileDb != null) { 2215720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro profileDb.setTransactionSuccessful(); 2216720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2217720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } finally { 22188d55bbc171bea632e960e0e5a88557cef5e66d92Dave Santoro mDb.endTransaction(); 2219720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (profileDb != null) { 2220720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro profileDb.endTransaction(); 2221720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2222720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2223720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro 2224720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (notifyChange) { 2225720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro notifyChange(); 2226720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2227720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro return numValues; 22287b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov } 22297b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov 22307b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov @Override 2231285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 2232bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2233b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 2234b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2235285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 22365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (inProfileMode()) { 22375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileAggregator.clearPendingAggregations(); 22385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileTransactionContext.clear(); 22395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 22405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactAggregator.clearPendingAggregations(); 22415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactTransactionContext.clear(); 22425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 2243b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2244b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2245285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2246285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2247285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 22481129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 2249bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2250b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 2251b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2252285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 2253b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 22545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().aggregateInTransaction(mTransactionContext.get(), mActiveDb.get()); 22551a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 22561a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 22575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().updateAllVisible(); 22581a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 22593826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 2260bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 2261bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov 22623826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatusUpdateNeeded) { 22633826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateProviderStatus(); 22643826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = false; 22653826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 2266b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2267b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2268bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov private void updateSearchIndexInTransaction() { 22695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> staleContacts = mTransactionContext.get().getStaleSearchIndexContactIds(); 22705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> staleRawContacts = mTransactionContext.get().getStaleSearchIndexRawContactIds(); 2271bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov if (!staleContacts.isEmpty() || !staleRawContacts.isEmpty()) { 2272bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov mSearchIndexManager.updateIndexForRawContacts(staleContacts, staleRawContacts); 22735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().clearSearchIndexUpdates(); 2274bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov } 2275bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov } 2276bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov 2277b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 2278bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2279b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 2280b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 22811129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 22825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro for (long rawContactId : mTransactionContext.get().getInsertedRawContactIds()) { 22835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().updateRawContactDisplayName(mActiveDb.get(), rawContactId); 22845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().onRawContactInsert(mTransactionContext.get(), mActiveDb.get(), 22855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro rawContactId); 228624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 228724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 22885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> dirtyRawContacts = mTransactionContext.get().getDirtyRawContactIds(); 2289d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (!dirtyRawContacts.isEmpty()) { 2290a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2291a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 2292d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov appendIds(mSb, dirtyRawContacts); 2293a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 22945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(mSb.toString()); 2295a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 2296a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 22975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> updatedRawContacts = mTransactionContext.get().getUpdatedRawContactIds(); 2298d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (!updatedRawContacts.isEmpty()) { 2299a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2300a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 2301d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov appendIds(mSb, updatedRawContacts); 2302a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 23035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(mSb.toString()); 2304b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2305b5a4add17815167d20a90645779df34cdf45280dFred Quintana 23065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Update sync states. 23075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro for (Map.Entry<Long, Object> entry : mTransactionContext.get().getUpdatedSyncStates()) { 2308b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 23095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().getSyncState().update(mActiveDb.get(), id, entry.getValue()) <= 0) { 23109d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana throw new IllegalStateException( 23119d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana "unable to update sync state, does it still exist?"); 23129d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana } 2313b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2314b5a4add17815167d20a90645779df34cdf45280dFred Quintana 23155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().clear(); 2316b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2317b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2318a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** 2319a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * Appends comma separated ids. 2320a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * @param ids Should not be empty 2321a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov */ 2322d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov private void appendIds(StringBuilder sb, Set<Long> ids) { 2323b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 2324a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(id).append(','); 2325b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2326a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2327a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 2328285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2329285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2330285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2331cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 233281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 233381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 233481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 233581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 233681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 233781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 233881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 2339cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 2340568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 234151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void setProviderStatus(int status) { 23423826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != status) { 23433826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatus = status; 23443826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov getContext().getContentResolver().notifyChange(ProviderStatus.CONTENT_URI, null, false); 23453826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 234651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 234751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 2348f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public DataRowHandler getDataRowHandler(final String mimeType) { 23495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (inProfileMode()) { 23505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return getDataRowHandlerForProfile(mimeType); 23515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 23533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 23546d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov handler = new DataRowHandlerForCustomMimetype( 23555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro getContext(), mContactsHelper, mContactAggregator, mimeType); 23563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 23573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 23583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 23593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 23603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 23615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public DataRowHandler getDataRowHandlerForProfile(final String mimeType) { 23625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro DataRowHandler handler = mProfileDataRowHandlers.get(mimeType); 23635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (handler == null) { 23645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handler = new DataRowHandlerForCustomMimetype( 23655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro getContext(), mProfileHelper, mProfileAggregator, mimeType); 23665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDataRowHandlers.put(mimeType, handler); 23675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return handler; 23695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 23714f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2372de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 2373bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 23741129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Log.v(TAG, "insertInTransaction: " + uri + " " + values); 2375b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2376f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 23775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 23785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 23795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 23805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 2382f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2383f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2384f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2385a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 2386a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 238735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2388a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 238935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 23905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 23915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = mDbHelper.get().getSyncState().insert(mActiveDb.get(), values); 239235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 239335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2394d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2395d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 23966bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 23976bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 23986bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 239924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: { 240024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro throw new UnsupportedOperationException( 240124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro "The profile contact is created automatically"); 240224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 240324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 2404d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS: 2405d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS: { 24065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = insertRawContact(uri, values, callerIsSyncAdapter); 2407f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2408a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2409a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2410a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2411d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_DATA: 2412d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID_DATA: { 2413d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro int segment = match == RAW_CONTACTS_DATA ? 1 : 2; 2414d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(segment)); 2415f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2416f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2417a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2418a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2419a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 24203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case RAW_CONTACTS_ID_STREAM_ITEMS: { 24213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.put(StreamItems.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 24223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItem(uri, values); 24233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 24270c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case DATA: 24280c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case PROFILE_DATA: { 2429f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2430f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2431a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2432a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2433a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2434ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2435f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertGroup(uri, values, callerIsSyncAdapter); 2436f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2437ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2438ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2439ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2440eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 24415aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 244243880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2443eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2444eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2445eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 24465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 24475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 244882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 24491f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 24501f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 24511f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 24523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 24533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItem(uri, values); 24543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 24583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 24593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItemPhoto(uri, values); 24603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 24643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 24653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.put(StreamItemPhotos.STREAM_ITEM_ID, uri.getPathSegments().get(1)); 24663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItemPhoto(uri, values); 24673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 2471a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 247281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2473f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 2474a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2475a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 24767e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 24777e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 24787e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 24797e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2480de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 2481a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2482a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2483a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2484e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * If account is non-null then store it in the values. If the account is 2485e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * already specified in the values then it must be consistent with the 2486e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * account, if it is non-null. 2487e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * 2488e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param uri Current {@link Uri} being operated on. 2489e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param values {@link ContentValues} to read and possibly update. 2490e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when only one of 2491e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_NAME} or 2492e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_TYPE} is specified, leaving the 2493e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * other undefined. 2494e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when {@link RawContacts#ACCOUNT_NAME} 2495e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * and {@link RawContacts#ACCOUNT_TYPE} are inconsistent between 2496e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * the given {@link Uri} and {@link ContentValues}. 24977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 2498e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey private Account resolveAccount(Uri uri, ContentValues values) throws IllegalArgumentException { 2499f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 2500f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 2501e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 2502f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2503f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 2504f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2505e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialValues = TextUtils.isEmpty(valueAccountName) 2506e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ^ TextUtils.isEmpty(valueAccountType); 2507e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2508e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri || partialValues) { 2509e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 25105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 2511fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 2512e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2513e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2514e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 2515e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 2516e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validUri = !TextUtils.isEmpty(accountName); 2517e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validValues = !TextUtils.isEmpty(valueAccountName); 2518e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2519e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validValues && validUri) { 2520e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Check that accounts match when both present 2521e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean accountMatch = TextUtils.equals(accountName, valueAccountName) 2522e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey && TextUtils.equals(accountType, valueAccountType); 2523e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (!accountMatch) { 25245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 2525fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "When both specified, ACCOUNT_NAME and ACCOUNT_TYPE must match", uri)); 2526e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2527e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validUri) { 2528e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Fill values from Uri when not present 2529f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, accountName); 2530f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, accountType); 2531e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validValues) { 2532f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountName = valueAccountName; 2533f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountType = valueAccountType; 2534e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else { 2535e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return null; 2536f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2537f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2538e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Use cached Account object when matches, otherwise create 2539f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mAccount == null 2540f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.name.equals(accountName) 2541f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.type.equals(accountType)) { 2542f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mAccount = new Account(accountName, accountType); 2543035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2544f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2545e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return mAccount; 25467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 254943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * Resolves the account and builds an {@link AccountWithDataSet} based on the data set specified 255043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * in the URI or values (if any). 255143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * @param uri Current {@link Uri} being operated on. 255243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * @param values {@link ContentValues} to read and possibly update. 255343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro */ 255443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro private AccountWithDataSet resolveAccountWithDataSet(Uri uri, ContentValues values) { 25553593682b8d9213fde576a0cff54458ad50563980Dave Santoro final Account account = resolveAccount(uri, values); 255643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro AccountWithDataSet accountWithDataSet = null; 255743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (account != null) { 255843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String dataSet = getQueryParameter(uri, RawContacts.DATA_SET); 255943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (dataSet == null) { 25603593682b8d9213fde576a0cff54458ad50563980Dave Santoro dataSet = values.getAsString(RawContacts.DATA_SET); 2561a71dc460ca951c7aca591f3f470c160cde70a1e3Dave Santoro } else { 25623593682b8d9213fde576a0cff54458ad50563980Dave Santoro values.put(RawContacts.DATA_SET, dataSet); 256343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 256443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet = new AccountWithDataSet(account.name, account.type, dataSet); 256543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 256643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro return accountWithDataSet; 256743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 256843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 256943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro /** 2570d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 25716bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 25726bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 25736bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 25746bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2575d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2576de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 25776bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 25786bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 25796bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 258024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * Inserts an item in the raw contacts table 2581a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2582f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param uri the values for the new row 2583f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param values the account this contact should be associated with. may be null. 2584dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana * @param callerIsSyncAdapter 2585a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2586a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 25875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private long insertRawContact(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 2588f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2589f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2590f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2591f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 259243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro AccountWithDataSet accountWithDataSet = resolveAccountWithDataSet(uri, mValues); 25937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25943d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 25953d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 2596f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 25973d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 25983d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 25995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long rawContactId = mActiveDb.get().insert(Tables.RAW_CONTACTS, 26005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro RawContacts.CONTACT_ID, mValues); 2601f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = RawContacts.AGGREGATION_MODE_DEFAULT; 26025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mValues.containsKey(RawContacts.AGGREGATION_MODE)) { 2603f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov aggregationMode = mValues.getAsInteger(RawContacts.AGGREGATION_MODE); 2604f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 26055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markNewForAggregation(rawContactId, aggregationMode); 2606285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 26075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Trigger creation of a Contact based on this RawContact at the end of transaction 26085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().rawContactInserted(rawContactId, accountWithDataSet); 2609f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2610dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 2611dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 2612dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long starred = values.getAsLong(RawContacts.STARRED); 2613dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (starred != null && starred != 0) { 2614dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred != 0); 2615dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2616dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2617dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 26183826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 2619023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2620a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2621a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2622dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void addAutoAddMembership(long rawContactId) { 2623dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID, 2624dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 2625dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 2626dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 2627dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2628dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2629dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2630dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private Long findGroupByRawContactId(String selection, long rawContactId) { 26315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.GROUPS + "," + Tables.RAW_CONTACTS, 26325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROJECTION_GROUP_ID, selection, 2633dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}, 2634dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana null /* groupBy */, null /* having */, null /* orderBy */); 2635dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 2636dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (c.moveToNext()) { 2637dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return c.getLong(0); 2638dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2639dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return null; 2640dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 2641dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana c.close(); 2642dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2643dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2644dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2645dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void updateFavoritesMembership(long rawContactId, boolean isStarred) { 2646dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID, 2647dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 2648dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 2649dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (isStarred) { 2650dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 2651dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 2652dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana deleteDataGroupMembership(rawContactId, groupId); 2653dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2654dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2655dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2656dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2657dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void insertDataGroupMembership(long rawContactId, long groupId) { 2658dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ContentValues groupMembershipValues = new ContentValues(); 2659dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.GROUP_ROW_ID, groupId); 2660dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.RAW_CONTACT_ID, rawContactId); 2661dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(DataColumns.MIMETYPE_ID, 26625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 26635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().insert(Tables.DATA, null, groupMembershipValues); 2664dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2665dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2666dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void deleteDataGroupMembership(long rawContactId, long groupId) { 2667dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final String[] selectionArgs = { 26685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Long.toString(mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)), 2669dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(groupId), 2670dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(rawContactId)}; 26715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.DATA, SELECTION_GROUPMEMBERSHIP_DATA, selectionArgs); 2672dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2673dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2674a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2675a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2676a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2677a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2678a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2679a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2680f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2681a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2682de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2683de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 268467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2685de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 268620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2687de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2688de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2689de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 26905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(DataColumns.PACKAGE_ID, mDbHelper.get().getPackageId(packageName)); 2691de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2692de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2693508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2694de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2695de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2696de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2697de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2698de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 26994097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 27005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.get().getMimeTypeId(mimeType)); 2701de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2702a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2703a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 27045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = rowHandler.insert(mActiveDb.get(), mTransactionContext.get(), rawContactId, mValues); 2705f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 27065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().markRawContactDirty(rawContactId); 2707a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 27085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().rawContactUpdated(rawContactId); 2709a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 27104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 27114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 27123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 27133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Inserts an item in the stream_items table. The account is checked against the 27143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account in the raw contact for which the stream item is being inserted. If the 27153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * new stream item results in more stream items under this raw contact than the limit, 27163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the oldest one will be deleted (note that if the stream item inserted was the 27173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * oldest, it will be immediately deleted, and this will return 0). 27183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 27193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param uri the insertion URI 27203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param values the values for the new row 27213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return the stream item _ID of the newly created row, or 0 if it was not created 27223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 27233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long insertStreamItem(Uri uri, ContentValues values) { 27243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long id = 0; 27253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.clear(); 27263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.putAll(values); 27273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = mValues.getAsLong(StreamItems.RAW_CONTACT_ID); 27293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Ensure that the raw contact exists and belongs to the caller's account. 27313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, mValues); 27323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, rawContactId); 27333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27346802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to insert accounts params - they don't exist in the stream items table. 27356802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_NAME); 27366802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_TYPE); 27376802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 27383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Insert the new stream item. 27395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = mActiveDb.get().insert(Tables.STREAM_ITEMS, null, mValues); 27406802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (id == -1) { 27416802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Insertion failed. 27426802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return 0; 27436802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 27443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check to see if we're over the limit for stream items under this raw contact. 27463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // It's possible that the inserted stream item is older than the the existing 27473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // ones, in which case it may be deleted immediately (resetting the ID to 0). 27483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = cleanUpOldStreamItems(rawContactId, id); 27493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return id; 27513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 27523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 27543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Inserts an item in the stream_item_photos table. The account is checked against 27553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the account in the raw contact that owns the stream item being modified. 27563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 27573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param uri the insertion URI 27583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param values the values for the new row 27596802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @return the stream item photo _ID of the newly created row, or 0 if there was an issue 27606802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * with processing the photo or creating the row 27613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 27623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long insertStreamItemPhoto(Uri uri, ContentValues values) { 27633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long id = 0; 27643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.clear(); 27653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.putAll(values); 27663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long streamItemId = mValues.getAsLong(StreamItemPhotos.STREAM_ITEM_ID); 27683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (streamItemId != 0) { 27693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = lookupRawContactIdForStreamId(streamItemId); 27703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Ensure that the raw contact exists and belongs to the caller's account. 27723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, mValues); 27733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, rawContactId); 27743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27756802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to insert accounts params - they don't exist in the stream item 27766802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // photos table. 27776802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_NAME); 27786802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_TYPE); 27793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27806802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Process the photo and store it. 27816802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (processStreamItemPhoto(mValues, false)) { 27826802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Insert the stream item photo. 27835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = mActiveDb.get().insert(Tables.STREAM_ITEM_PHOTOS, null, mValues); 27846802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 27853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 27863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return id; 27873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 27883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 27906802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * Processes the photo contained in the {@link ContactsContract.StreamItemPhotos#PHOTO} 27916802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * field of the given values, attempting to store it in the photo store. If successful, 27926802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * the resulting photo file ID will be added to the values for insert/update in the table. 27936802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * <p> 27946802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * If updating, it is valid for the picture to be empty or unspecified (the function will 27956802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * still return true). If inserting, a valid picture must be specified. 27966802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @param values The content values provided by the caller. 27976802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @param forUpdate Whether this photo is being processed for update (vs. insert). 27986802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @return Whether the insert or update should proceed. 27996802030a777c0c3ba1dc029c534cca4784260632Dave Santoro */ 28006802030a777c0c3ba1dc029c534cca4784260632Dave Santoro private boolean processStreamItemPhoto(ContentValues values, boolean forUpdate) { 28016802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (!values.containsKey(StreamItemPhotos.PHOTO)) { 28026802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return forUpdate; 28036802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28046802030a777c0c3ba1dc029c534cca4784260632Dave Santoro byte[] photoBytes = values.getAsByteArray(StreamItemPhotos.PHOTO); 28056802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoBytes == null) { 28066802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return forUpdate; 28076802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28086802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 28096802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Process the photo and store it. 28106802030a777c0c3ba1dc029c534cca4784260632Dave Santoro try { 28115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long photoFileId = mPhotoStore.get().insert(new PhotoProcessor(photoBytes, 28121dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro mMaxDisplayPhotoDim, mMaxThumbnailPhotoDim, true), true); 28136802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoFileId != 0) { 28146802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.put(StreamItemPhotos.PHOTO_FILE_ID, photoFileId); 28156802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(StreamItemPhotos.PHOTO); 28166802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return true; 28176802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } else { 28186802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Couldn't store the photo, return 0. 28196802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Log.e(TAG, "Could not process stream item photo for insert"); 28206802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return false; 28216802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28226802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } catch (IOException ioe) { 28236802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Log.e(TAG, "Could not process stream item photo for insert", ioe); 28246802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return false; 28256802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28266802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28276802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 28286802030a777c0c3ba1dc029c534cca4784260632Dave Santoro /** 28293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Looks up the raw contact ID that owns the specified stream item. 28303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param streamItemId The ID of the stream item. 28313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The associated raw contact ID, or -1 if no such stream item exists. 28323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 28333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long lookupRawContactIdForStreamId(long streamItemId) { 28343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = -1; 28355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, 28365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{StreamItems.RAW_CONTACT_ID}, 28373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItems._ID + "=?", new String[]{String.valueOf(streamItemId)}, 28383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 28393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 28403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (c.moveToFirst()) { 28413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann rawContactId = c.getLong(0); 28423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 28443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 28453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return rawContactId; 28473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 28493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 28503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given raw contact ID is owned by the given account. 28513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * If the resolved account is null, this will return true iff the raw contact 28523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * is also associated with the "null" account. 28533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 28543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * If the resolved account does not match, this will throw a security exception. 28553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 28563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param rawContactId The raw contact ID to check for. 28573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 28583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void enforceModifyingAccount(Account account, long rawContactId) { 28593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String accountSelection = RawContactsColumns.CONCRETE_ID + "=? AND " 28603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_NAME + "=? AND " 28613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + "=?"; 28623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String noAccountSelection = RawContactsColumns.CONCRETE_ID + "=? AND " 28633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL AND " 28643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL"; 28653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Cursor c; 28663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (account != null) { 28675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro c = mActiveDb.get().query(Tables.RAW_CONTACTS, 28685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{RawContactsColumns.CONCRETE_ID}, accountSelection, 28693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(rawContactId), mAccount.name, mAccount.type}, 28703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 28713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } else { 28725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro c = mActiveDb.get().query(Tables.RAW_CONTACTS, 28735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{RawContactsColumns.CONCRETE_ID}, noAccountSelection, 28745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{String.valueOf(rawContactId)}, 28753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 28763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 28783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if(c.getCount() == 0) { 28793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann throw new SecurityException("Caller account does not match raw contact ID " 28803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + rawContactId); 28813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 28833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 28843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 28873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 28883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given selection of stream items matches up with the given 28893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account. If any of the raw contacts fail the account check, this will throw a 28903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * security exception. 28913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 28923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selection The selection. 28933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selectionArgs The selection arguments. 28943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The list of stream item IDs that would be included in this selection. 28953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 28963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private List<Long> enforceModifyingAccountForStreamItems(Account account, String selection, 28973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 28983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemIds = Lists.newArrayList(); 28993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 29003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 29015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), 29023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{StreamItems._ID, StreamItems.RAW_CONTACT_ID}, 29033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selection, selectionArgs, null, null, null); 29043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 29053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.moveToNext()) { 29063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann streamItemIds.add(c.getLong(0)); 29073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Throw a security exception if the account doesn't match the raw contact's. 29093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, c.getLong(1)); 29103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 29123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 29133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemIds; 29153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 29183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given selection of stream item photos matches up with the given 29193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account. If any of the raw contacts fail the account check, this will throw a 29203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * security exception. 29213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 29223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selection The selection. 29233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selectionArgs The selection arguments. 29243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The list of stream item photo IDs that would be included in this selection. 29253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 29263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private List<Long> enforceModifyingAccountForStreamItemPhotos(Account account, String selection, 29273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 29283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemPhotoIds = Lists.newArrayList(); 29293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 29303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 29315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), 29325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{StreamItemPhotos._ID, StreamItems.RAW_CONTACT_ID}, 29333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selection, selectionArgs, null, null, null); 29343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 29353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.moveToNext()) { 29363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann streamItemPhotoIds.add(c.getLong(0)); 29373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Throw a security exception if the account doesn't match the raw contact's. 29393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, c.getLong(1)); 29403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 29423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 29433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemPhotoIds; 29453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 29483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Queries the database for stream items under the given raw contact. If there are 29493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * more entries than {@link ContactsProvider2#MAX_STREAM_ITEMS_PER_RAW_CONTACT}, 29503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the oldest entries (as determined by timestamp) will be deleted. 29513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param rawContactId The raw contact ID to examine for stream items. 29523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param insertedStreamItemId The ID of the stream item that was just inserted, 29533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * prompting this cleanup. Callers may pass 0 if no insertion prompted the 29543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * cleanup. 29553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The ID of the inserted stream item if it still exists after cleanup; 29563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 0 otherwise. 29573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 29583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long cleanUpOldStreamItems(long rawContactId, long insertedStreamItemId) { 29593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long postCleanupInsertedStreamId = insertedStreamItemId; 29605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, new String[]{StreamItems._ID}, 29613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItems.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)}, 29623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, StreamItems.TIMESTAMP + " DESC, " + StreamItems._ID + " DESC"); 29633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 29643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann int streamItemCount = c.getCount(); 29653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (streamItemCount <= MAX_STREAM_ITEMS_PER_RAW_CONTACT) { 29663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Still under the limit - nothing to clean up! 29673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return insertedStreamItemId; 29683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } else { 29693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.moveToLast(); 29703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.getPosition() >= MAX_STREAM_ITEMS_PER_RAW_CONTACT) { 29713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long streamItemId = c.getLong(0); 29723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (insertedStreamItemId == streamItemId) { 29733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // The stream item just inserted is being deleted. 29743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann postCleanupInsertedStreamId = 0; 29753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItem(c.getLong(0)); 29773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.moveToPrevious(); 29783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 29813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 29823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return postCleanupInsertedStreamId; 29843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29869261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 298720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 298820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2989f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 299020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 299120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2992de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2993de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 29940c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro Uri dataUri = inProfileMode() 29950c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro ? Uri.withAppendedPath(Profile.CONTENT_URI, RawContacts.Data.CONTENT_DIRECTORY) 29960c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro : Data.CONTENT_URI; 29970c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro Cursor c = query(dataUri, DataRowHandler.DataDeleteQuery.COLUMNS, 2998f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov selection, selectionArgs, null); 2999de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 3000de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 3001f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov long rawContactId = c.getLong(DataRowHandler.DataDeleteQuery.RAW_CONTACT_ID); 3002f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE); 3003a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 30045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro count += rowHandler.delete(mActiveDb.get(), mTransactionContext.get(), c); 3005f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 30065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().markRawContactDirty(rawContactId); 300788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 300820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 300920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 3010de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 301120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 301220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 301320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 301420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 301520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 301688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 301788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 301888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 301920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 3020f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 302188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 302288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 30234da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 3024f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataRowHandler.DataDeleteQuery.COLUMNS, Data._ID + "=?", 30254da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null); 3026f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 302720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 302820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 302920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 303020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 303120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3032f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE); 303320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 303420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 303520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 303620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 303720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 303820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 303920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 304020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 304120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 30427a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 304320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 304420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3045a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 30465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return rowHandler.delete(mActiveDb.get(), mTransactionContext.get(), c); 304720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 304820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 304920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 305020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 305120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 305220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 3053ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 3054ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 3055f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 3056f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 3057f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 3058f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 30593593682b8d9213fde576a0cff54458ad50563980Dave Santoro final AccountWithDataSet accountWithDataSet = resolveAccountWithDataSet(uri, mValues); 3060ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3061ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 3062f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String packageName = mValues.getAsString(Groups.RES_PACKAGE); 306367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 30645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.get().getPackageId(packageName)); 306567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 3066f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.remove(Groups.RES_PACKAGE); 3067ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3068dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final boolean isFavoritesGroup = mValues.getAsLong(Groups.FAVORITES) != null 3069dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ? mValues.getAsLong(Groups.FAVORITES) != 0 3070dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana : false; 3071dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3072f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 3073f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(Groups.DIRTY, 1); 307473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 307573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 30765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long result = mActiveDb.get().insert(Tables.GROUPS, Groups.TITLE, mValues); 3077ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 3078dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && isFavoritesGroup) { 3079dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // add all starred raw contacts to this group 3080dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String selection; 3081dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs; 30823593682b8d9213fde576a0cff54458ad50563980Dave Santoro if (accountWithDataSet == null) { 3083dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + " IS NULL AND " 308443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.ACCOUNT_TYPE + " IS NULL AND " 308543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.DATA_SET + " IS NULL"; 3086dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selectionArgs = null; 30873593682b8d9213fde576a0cff54458ad50563980Dave Santoro } else if (accountWithDataSet.getDataSet() == null) { 3088dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + "=? AND " 30893593682b8d9213fde576a0cff54458ad50563980Dave Santoro + RawContacts.ACCOUNT_TYPE + "=? AND " 30903593682b8d9213fde576a0cff54458ad50563980Dave Santoro + RawContacts.DATA_SET + " IS NULL"; 30913593682b8d9213fde576a0cff54458ad50563980Dave Santoro selectionArgs = new String[] { 30923593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountName(), 30933593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountType() 30943593682b8d9213fde576a0cff54458ad50563980Dave Santoro }; 309543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } else { 309643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro selection = RawContacts.ACCOUNT_NAME + "=? AND " 309743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.ACCOUNT_TYPE + "=? AND " 309843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.DATA_SET + "=?"; 30993593682b8d9213fde576a0cff54458ad50563980Dave Santoro selectionArgs = new String[] { 31003593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountName(), 31013593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountType(), 31023593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getDataSet() 31033593682b8d9213fde576a0cff54458ad50563980Dave Santoro }; 3104dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 31055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, 3106dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{RawContacts._ID, RawContacts.STARRED}, 3107dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection, selectionArgs, null, null, null); 3108892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov try { 3109892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov while (c.moveToNext()) { 3110892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (c.getLong(1) != 0) { 3111892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov final long rawContactId = c.getLong(0); 3112892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov insertDataGroupMembership(rawContactId, result); 31135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().markRawContactDirty(rawContactId); 3114892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 3115dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3116892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } finally { 3117892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov c.close(); 3118dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3119dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3120dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3121f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mValues.containsKey(Groups.GROUP_VISIBLE)) { 31221a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3123ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 3124ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 3125ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 3126ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3127ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 31285aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 3129f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro // Before inserting, ensure that no settings record already exists for the 3130f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro // values being inserted (this used to be enforced by a primary key, but that no 3131f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro // longer works with the nullable data_set field added). 3132f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro String accountName = values.getAsString(Settings.ACCOUNT_NAME); 3133f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro String accountType = values.getAsString(Settings.ACCOUNT_TYPE); 3134f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro String dataSet = values.getAsString(Settings.DATA_SET); 3135f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro Uri.Builder settingsUri = Settings.CONTENT_URI.buildUpon(); 3136f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (accountName != null) { 3137f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro settingsUri.appendQueryParameter(Settings.ACCOUNT_NAME, accountName); 3138f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3139f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (accountType != null) { 3140f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro settingsUri.appendQueryParameter(Settings.ACCOUNT_TYPE, accountType); 3141f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3142f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (dataSet != null) { 3143f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro settingsUri.appendQueryParameter(Settings.DATA_SET, dataSet); 3144f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3145f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro Cursor c = queryLocal(settingsUri.build(), null, null, null, null, 0); 3146f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro try { 3147f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (c.getCount() > 0) { 3148f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro throw new SQLiteConstraintException("Can't insert a settings record with the same " 3149f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + "account name/type/data set"); 3150f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3151f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } finally { 3152f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro c.close(); 3153f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } 3154f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro 3155f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro // If we didn't find a duplicate, we're fine to insert. 31565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long id = mActiveDb.get().insert(Tables.SETTINGS, null, values); 31575aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 31581a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 31591a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3160e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 31611a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 3162e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 3163e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3164e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3165ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 316682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 31671f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 316882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 316982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 31700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 31714dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 31724dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 31730a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 317482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 31754dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 31764dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 31774dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 31784dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 31791f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 31801f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3181dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 3182dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 318382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 31846802030a777c0c3ba1dc029c534cca4784260632Dave Santoro String accountType = null; 31856802030a777c0c3ba1dc029c534cca4784260632Dave Santoro String accountName = null; 3186f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 31872526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.clear(); 3188dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 3189dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 3190dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 31912526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "=?"); 31922526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(dataId)); 31931f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 3194dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 3195dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 31960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 31970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 31980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 31990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3200dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 3201dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 3202dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 32035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String mimeTypeIdIm = String.valueOf(mDbHelper.get().getMimeTypeIdForIm()); 3204dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 32055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String mimeTypeIdEmail = String.valueOf(mDbHelper.get().getMimeTypeIdForEmail()); 3206f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3207f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 3208f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 3209f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 3210f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3211f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 3212f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 32132526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (?,?)" + 32142526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Data.DATA1 + "=?" + 32152526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND ((" + DataColumns.MIMETYPE_ID + "=? AND " + Im.PROTOCOL + "=?"); 32162526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 32172526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32182526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 32192526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32202526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 3221dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 32222526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 32232526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3224dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 32252526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=?))"); 32262526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 3227dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 32282526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=?" + 32292526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.PROTOCOL + "=?" + 32302526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.DATA + "=?"); 32312526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32322526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 32332526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 3234dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 32352526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 32362526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3237dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 3238dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 32391f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 324082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 32412526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=?"); 32422526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(values.getAsString(StatusUpdates.DATA_ID)); 3243dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 324470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 324570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 32461f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 32471f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 32485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro cursor = mActiveDb.get().query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 32492526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.toString(), mSelectionArgs.toArray(EMPTY_STRING_ARRAY), null, null, 32504394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov Clauses.CONTACT_VISIBLE + " DESC, " + Data.RAW_CONTACT_ID); 32511f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 325267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 32535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 32546802030a777c0c3ba1dc029c534cca4784260632Dave Santoro accountType = cursor.getString(DataContactsQuery.ACCOUNT_TYPE); 32556802030a777c0c3ba1dc029c534cca4784260632Dave Santoro accountName = cursor.getString(DataContactsQuery.ACCOUNT_NAME); 3256e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 32571f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 32581f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 32591f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 32601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 32611f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 326231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 326331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 326431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 32651f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 32661f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 326782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 3268a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 3269a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 3270a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 3271a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 3272a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3273a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3274a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 327582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 3276a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 3277a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 327882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 327982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 328082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 328182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 328282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 3283a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 328482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 328582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 3286aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori mValues.put(StatusUpdates.CHAT_CAPABILITY, 3287aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori values.getAsString(StatusUpdates.CHAT_CAPABILITY)); 32881f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3289a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 32905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().replace(Tables.PRESENCE, null, mValues); 3291a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3292e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 32930a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 329482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 329582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 32960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 32970bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Resources resources = getContext().getResources(); 32980bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if (!TextUtils.isEmpty(resPackage)) { 32990bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann PackageManager pm = getContext().getPackageManager(); 33000bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann try { 33010bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann resources = pm.getResourcesForApplication(resPackage); 33020bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } catch (NameNotFoundException e) { 33030bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Log.w(TAG, "Contact status update resource package not found: " 33040bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + resPackage); 33050bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 33060bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 33070bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Integer labelResourceId = values.getAsInteger(StatusUpdates.STATUS_LABEL); 33080a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 33090bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if ((labelResourceId == null || labelResourceId == 0) && protocol != null) { 33100bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann labelResourceId = Im.getProtocolLabelResource(protocol); 33110a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 33120bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann String labelResource = getResourceName(resources, "string", labelResourceId); 33130a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 33140bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Integer iconResourceId = values.getAsInteger(StatusUpdates.STATUS_ICON); 33150a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 33160a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 33170bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann String iconResource = getResourceName(resources, "drawable", iconResourceId); 33180bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 3319a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 33205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().deleteStatusUpdate(dataId); 3321a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 33226802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 33236802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (timestamp != null) { 33245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().replaceStatusUpdate(dataId, timestamp, status, resPackage, 33250bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann iconResourceId, labelResourceId); 33266802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } else { 33275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().insertStatusUpdate(dataId, status, resPackage, iconResourceId, 33280bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann labelResourceId); 33296802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 33306802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 33316802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // For forward compatibility with the new stream item API, insert this status update 33326802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // there as well. If we already have a stream item from this source, update that 33336802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // one instead of inserting a new one (since the semantics of the old status update 33346802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // API is to only have a single record). 33356802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (rawContactId != -1 && !TextUtils.isEmpty(status)) { 33366802030a777c0c3ba1dc029c534cca4784260632Dave Santoro ContentValues streamItemValues = new ContentValues(); 33376802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RAW_CONTACT_ID, rawContactId); 3338d5ef5903570e533a501abe6a8e3d533fdb5318fcFlavio Lerda // Status updates are text only but stream items are HTML. 3339e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda streamItemValues.put(StreamItems.TEXT, statusUpdateToHtml(status)); 33406802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.COMMENTS, ""); 33416802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RES_PACKAGE, resPackage); 33426802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RES_ICON, iconResource); 33436802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RES_LABEL, labelResource); 33446802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.TIMESTAMP, 33456802030a777c0c3ba1dc029c534cca4784260632Dave Santoro timestamp == null ? System.currentTimeMillis() : timestamp); 33466802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 33476802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Note: The following is basically a workaround for the fact that status 33486802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // updates didn't do any sort of account enforcement, while social stream item 33496802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // updates do. We can't expect callers of the old API to start passing account 33506802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // information along, so we just populate the account params appropriately for 335143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // the raw contact. Data set is not relevant here, as we only check account 335243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // name and type. 33536802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (accountName != null && accountType != null) { 33546802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(RawContacts.ACCOUNT_NAME, accountName); 33556802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(RawContacts.ACCOUNT_TYPE, accountType); 33566802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 33576802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 33586802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Check for an existing stream item from this source, and insert or update. 33596802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Uri streamUri = StreamItems.CONTENT_URI; 33606802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Cursor c = query(streamUri, new String[]{StreamItems._ID}, 33616802030a777c0c3ba1dc029c534cca4784260632Dave Santoro StreamItems.RAW_CONTACT_ID + "=?", 33626802030a777c0c3ba1dc029c534cca4784260632Dave Santoro new String[]{String.valueOf(rawContactId)}, null); 33636802030a777c0c3ba1dc029c534cca4784260632Dave Santoro try { 33646802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (c.getCount() > 0) { 33656802030a777c0c3ba1dc029c534cca4784260632Dave Santoro c.moveToFirst(); 33666802030a777c0c3ba1dc029c534cca4784260632Dave Santoro update(ContentUris.withAppendedId(streamUri, c.getLong(0)), 33676802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues, null, null); 33686802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } else { 33696802030a777c0c3ba1dc029c534cca4784260632Dave Santoro insert(streamUri, streamItemValues); 33706802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 33716802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } finally { 33726802030a777c0c3ba1dc029c534cca4784260632Dave Santoro c.close(); 33736802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 33746802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 3375e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3376e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3377bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 3378a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 33795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateLastStatusUpdateId(contactId); 3380a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3381a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3382a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 33831f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 33841f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3385e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda /** Converts a status update to HTML. */ 3386e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda private String statusUpdateToHtml(String status) { 33874747809486541f7a3d342d3e1dd48fb5ea255ad6Flavio Lerda return TextUtils.htmlEncode(status); 3388e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda } 3389e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda 33900bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann private String getResourceName(Resources resources, String expectedType, Integer resourceId) { 33910bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann try { 33920bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if (resourceId == null || resourceId == 0) return null; 33930bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 33940bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann // Resource has an invalid type (e.g. a string as icon)? ignore 33950bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann final String resourceEntryName = resources.getResourceEntryName(resourceId); 33960bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann final String resourceTypeName = resources.getResourceTypeName(resourceId); 33970bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if (!expectedType.equals(resourceTypeName)) { 33980bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Log.w(TAG, "Resource " + resourceId + " (" + resourceEntryName + ") is of type " + 33990bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann resourceTypeName + " but " + expectedType + " is required."); 34000bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann return null; 34010bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 34020bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 34030bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann return resourceEntryName; 34040bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } catch (NotFoundException e) { 34050bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann return null; 34060bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 34070bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 34080bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 34094f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3410de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 3411bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3412b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 3413b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 34145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 34155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 34165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 34175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 34185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 34195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 3420b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3421f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3422f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 3423508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 3424508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 342535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 34265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 34275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().delete(mActiveDb.get(), selection, 34285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 34295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 34305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case SYNCSTATE_ID: { 34315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String selectionWithId = 34325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 34335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro + (selection == null ? "" : " AND (" + selection + ")"); 34345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().delete(mActiveDb.get(), selectionWithId, 34355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 34365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 343735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 34385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE_ID: { 3439b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3440b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3441b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 34425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileHelper.getSyncState().delete(mActiveDb.get(), selectionWithId, 34435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 34445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 3445b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3446cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 3447cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 3448cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 3449cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3450cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3451d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3452d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3453dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 34546bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 34556bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 34569fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP: { 34572e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 34582e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 34592e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 34605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 3461fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 34622e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 34632e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 34645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 3465dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 34662e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 34672e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 34689fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP_ID: { 34699fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // lookup contact by id and lookup key to see if they still match the actual record 34709fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final List<String> pathSegments = uri.getPathSegments(); 34719fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final String lookupKey = pathSegments.get(2); 34729fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 34739fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann setTablesAndProjectionMapForContacts(lookupQb, uri, null); 3474a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 34759fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann String[] args; 34769fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (selectionArgs == null) { 34779fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[2]; 34789fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 34799fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[selectionArgs.length + 2]; 34809fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 34819fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34829fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args[0] = String.valueOf(contactId); 348360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann args[1] = Uri.encode(lookupKey); 34849fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 34855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = query(mActiveDb.get(), lookupQb, null, selection, args, null, null, 34865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro null); 34879fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann try { 34889fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (c.getCount() == 1) { 34899fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // contact was unmodified so go ahead and delete it 3490dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 34919fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 34929fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // row was changed (e.g. the merging might have changed), we got multiple 34939fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // rows or the supplied selection filtered the record out 34949fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return 0; 34959fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34969fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } finally { 34979fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann c.close(); 34989fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34999fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 35009fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 3501d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS: 3502d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS: { 35032971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 35045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, 3505fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov new String[]{RawContacts._ID, RawContacts.CONTACT_ID}, 3506e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 35072971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 35082971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 35092971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 3510fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov long contactId = c.getLong(1); 3511fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov numDeletes += deleteRawContact(rawContactId, contactId, 3512fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 35132971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35142971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 35152971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 35162971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35172971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 35182971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35192971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 3520d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_ID: 3521d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID: { 35222971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 35235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return deleteRawContact(rawContactId, mDbHelper.get().getContactId(rawContactId), 3524fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 3525508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3526508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 35270c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case DATA: 35280c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case PROFILE_DATA: { 3529f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 3530944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 3531f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 353220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 353320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 353448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 353548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 353648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 3537d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case POSTALS_ID: 3538d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_DATA_ID: { 3539508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 3540f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 35414da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 35424da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return deleteData(Data._ID + "=?", mSelectionArgs1, callerIsSyncAdapter); 3543ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3544ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3545ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3546f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 35475aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 35482971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35492971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 35502971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 35512971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 35525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.GROUPS, new String[]{Groups._ID}, 3553e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 35542971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 35552971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 35565aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 35572971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35582971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 35592971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 35602971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 356181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 3562f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 356381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 35642971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 3565508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3566508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 3567eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 356843880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3569e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return deleteSettings(uri, appendAccountToSelection(uri, selection), selectionArgs); 3570eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3571eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 35725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 35735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 35740a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 35751f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 35761f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 35773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 35783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 35793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItems(uri, new ContentValues(), selection, selectionArgs); 35803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 35813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 35823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 35833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 35843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItems(uri, new ContentValues(), 35859b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann StreamItems._ID + "=?", 35863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{uri.getLastPathSegment()}); 35873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 35883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 358982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro case RAW_CONTACTS_ID_STREAM_ITEMS_ID: { 359082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro mSyncToNetwork |= !callerIsSyncAdapter; 359182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String rawContactId = uri.getPathSegments().get(1); 359282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String streamItemId = uri.getLastPathSegment(); 359382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro return deleteStreamItems(uri, new ContentValues(), 359482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems.RAW_CONTACT_ID + "=? AND " + StreamItems._ID + "=?", 359582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro new String[]{rawContactId, streamItemId}); 359682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 359782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 359882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 35993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 36003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 36015d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro String streamItemId = uri.getPathSegments().get(1); 36025d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro String selectionWithId = 36035d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro (StreamItemPhotos.STREAM_ITEM_ID + "=" + streamItemId + " ") 36045d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro + (selection == null ? "" : " AND (" + selection + ")"); 36055d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro return deleteStreamItemPhotos(uri, new ContentValues(), 36065d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro selectionWithId, selectionArgs); 36073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 36083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 36093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 36103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 36113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 36123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 36133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItemPhotos(uri, new ContentValues(), 36143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=? AND " 36153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + StreamItemPhotos.STREAM_ITEM_ID + "=?", 36163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{streamItemPhotoId, streamItemId}); 36173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 36183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 361981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 362081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 36213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 362281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3623508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 36244f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 36254f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 36261c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 3627ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 36285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long groupMembershipMimetypeId = mDbHelper.get() 362994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 36305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 363194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 363294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 363394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 363494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 3635f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 36365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 363794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 363894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 363994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 3640f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 36415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, 36425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro null); 364394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 364494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 36451a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 364694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 364794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 364894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 36495aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 36505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final int count = mActiveDb.get().delete(Tables.SETTINGS, selection, selectionArgs); 36511a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3652e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3653e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3654e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3655dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int deleteContact(long contactId, boolean callerIsSyncAdapter) { 365696b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(contactId); 36575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 365896b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker RawContacts.CONTACT_ID + "=?", mSelectionArgs1, 365996b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker null, null, null); 3660cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 3661cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 3662cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 3663dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 3664cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3665cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 3666cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 3667cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3668cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 36693826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 36703826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 36715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 3672cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3673cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3674fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) { 36755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().invalidateAggregationExceptionCache(); 36763826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 36773826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 367882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro // Find and delete stream items associated with the raw contact. 367982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, 368082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro new String[]{StreamItems._ID}, 368182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)}, 368282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro null, null, null); 368382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro try { 368482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro while (c.moveToNext()) { 368582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro deleteStreamItem(c.getLong(0)); 368682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 368782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } finally { 368882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro c.close(); 368982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 369082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 3691d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro if (callerIsSyncAdapter || rawContactIsLocal(rawContactId)) { 36925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.PRESENCE, 36935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 36945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int count = mActiveDb.get().delete(Tables.RAW_CONTACTS, 36955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro RawContacts._ID + "=" + rawContactId, null); 36965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateDisplayNameForContact(mActiveDb.get(), contactId); 3697fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return count; 369833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 36995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().removeContactIfSingleton(rawContactId); 3700dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 370133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 370233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 370333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 3704d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro /** 3705d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro * Returns whether the given raw contact ID is local (i.e. has no account associated with it). 3706d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro */ 3707d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro private boolean rawContactIsLocal(long rawContactId) { 3708d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, 3709d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro new String[] { 3710d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro RawContacts.ACCOUNT_NAME, 3711d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro RawContacts.ACCOUNT_TYPE, 3712d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro RawContacts.DATA_SET 3713d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro }, 3714d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro RawContacts._ID + "=?", 3715d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro new String[] {String.valueOf(rawContactId)}, null, null, null); 3716d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro try { 3717d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro return c.moveToFirst() && c.isNull(0) && c.isNull(1) && c.isNull(2); 3718d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro } finally { 3719d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro c.close(); 3720d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro } 3721d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro } 3722d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro 37230a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 37249705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // delete from both tables: presence and status_updates 37259705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 37269705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (VERBOSE_LOGGING) { 37279705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Log.v(TAG, "deleting data from status_updates for " + selection); 37289705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 37295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 37309705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 37315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.PRESENCE, selection, selectionArgs); 37320a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 37330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 37343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItems(Uri uri, ContentValues values, String selection, 37353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 37363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // First query for the stream items to be deleted, and check that they belong 37373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // to the account. 37383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 37393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemIds = enforceModifyingAccountForStreamItems( 37403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann account, selection, selectionArgs); 37413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If no security exception has been thrown, we're fine to delete. 37433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann for (long streamItemId : streamItemIds) { 37443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItem(streamItemId); 37453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mVisibleTouched = true; 37483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemIds.size(); 37493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItem(long streamItemId) { 37523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Note that this does not enforce the modifying account. 37533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItemPhotos(streamItemId); 37545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.STREAM_ITEMS, StreamItems._ID + "=?", 37553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(streamItemId)}); 37563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItemPhotos(Uri uri, ContentValues values, String selection, 37593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 37603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // First query for the stream item photos to be deleted, and check that they 37613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // belong to the account. 37623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 37633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItemPhotos(account, selection, selectionArgs); 37643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If no security exception has been thrown, we're fine to delete. 37665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.STREAM_ITEM_PHOTOS, selection, selectionArgs); 37673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItemPhotos(long streamItemId) { 37703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Note that this does not enforce the modifying account. 37715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.STREAM_ITEM_PHOTOS, 37725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro StreamItemPhotos.STREAM_ITEM_ID + "=?", 37733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(streamItemId)}); 37743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 3776dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int markRawContactAsDeleted(long rawContactId, boolean callerIsSyncAdapter) { 377781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 377881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 3779cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 3780cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 3781cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 3782cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 3783cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 3784cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3785dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return updateRawContact(rawContactId, mValues, callerIsSyncAdapter); 3786cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3787cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 37884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3789de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 3790de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 3791bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3792b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 3793b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3794b5a4add17815167d20a90645779df34cdf45280dFred Quintana 37955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 37965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 37975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 37985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 37995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 380035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 380100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 380200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 3803b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 3804b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 38051129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Object data = values.get(ContactsContract.SyncState.DATA); 38065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().syncStateUpdated(rowId, data); 3807b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 3808b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3809b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3810f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3811f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 381200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 381335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 38145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 38155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().update(mActiveDb.get(), values, 3816b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 3817b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3818b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 3819b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 3820b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3821b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3822b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 38235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().update(mActiveDb.get(), values, 38245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionWithId, selectionArgs); 38255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 38265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 38275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE_ID: { 38285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection = appendAccountToSelection(uri, selection); 38295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String selectionWithId = 38305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 38315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro + (selection == null ? "" : " AND (" + selection + ")"); 38325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileHelper.getSyncState().update(mActiveDb.get(), values, 3833b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 3834b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 383535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3836d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case CONTACTS: 3837d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE: { 3838dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(values, selection, selectionArgs, callerIsSyncAdapter); 383900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 384000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 384100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3842d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3843dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(ContentUris.parseId(uri), values, callerIsSyncAdapter); 3844c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 3845c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 3846c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 38472e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 38482e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 38492e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 38502e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 38512e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 38525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 3853fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 38542e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 38552e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 38565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 3857dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(contactId, values, callerIsSyncAdapter); 38582e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 38592e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 38602e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 3861d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_DATA: 3862d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID_DATA: { 3863d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro int segment = match == RAW_CONTACTS_DATA ? 1 : 2; 3864d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro final String rawContactId = uri.getPathSegments().get(segment); 38657d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 38667d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 38677d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 38687d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 38697d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 38707d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 38717d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 38727d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 38730c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case DATA: 38740c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case PROFILE_DATA: { 3875944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 3876f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 387781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3878f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 387981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 388020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 388120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3882c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 388348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 388448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 388548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 388648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3887f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 388881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3889f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 389081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 389100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 389200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 38937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 38945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case RAW_CONTACTS: 38955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_RAW_CONTACTS: { 38965ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 3897dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, selection, selectionArgs, callerIsSyncAdapter); 38987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 38997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 39015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 390233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 39034529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 39044da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 39054da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?" 3906dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND(" + selection + ")", selectionArgs, 3907dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 39084529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 39094da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 3910dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, RawContacts._ID + "=?", mSelectionArgs1, 3911dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 39124529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 39137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 39147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 39157e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3916ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 39175aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 3918f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 391981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3920f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 392181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3922ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3923ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3924ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3925ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3926ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 39274da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(groupId)); 39284da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String selectionWithId = Groups._ID + "=? " 392973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 39305aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 39315aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 393281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3933f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 393481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3935ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3936ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3937ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3938127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 39395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro count = updateAggregationException(mActiveDb.get(), values); 3940b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3941b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3942b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3943eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3944e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey count = updateSettings(uri, values, appendAccountToSelection(uri, selection), 3945e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey selectionArgs); 394643880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3947eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3948eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3949eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 39505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 39515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 39529705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori count = updateStatusUpdate(uri, values, selection, selectionArgs); 39539705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori break; 39549705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 39559705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 39563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 39573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItems(uri, values, selection, selectionArgs); 39583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 39613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 39629b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann count = updateStreamItems(uri, values, StreamItems._ID + "=?", 39633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{uri.getLastPathSegment()}); 39643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 396782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro case RAW_CONTACTS_ID_STREAM_ITEMS_ID: { 396882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String rawContactId = uri.getPathSegments().get(1); 396982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String streamItemId = uri.getLastPathSegment(); 397082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro count = updateStreamItems(uri, values, 397182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems.RAW_CONTACT_ID + "=? AND " + StreamItems._ID + "=?", 397282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro new String[]{rawContactId, streamItemId}); 397382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro break; 397482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 397582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 39763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 39773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, selection, selectionArgs); 39783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 39813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 39823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 39833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, 39843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotos.STREAM_ITEM_ID + "=?", new String[]{streamItemId}); 39853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 39883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 39893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 39903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 39913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, 39923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=? AND " + 39933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=?", 39943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{streamItemPhotoId, streamItemId}); 39953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 399872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case DIRECTORIES: { 3999bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.scanPackagesByUid(Binder.getCallingUid()); 400072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov count = 1; 4001d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 4002d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4003d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 400446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa case DATA_USAGE_FEEDBACK_ID: { 400546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (handleDataUsageFeedback(uri)) { 400646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa count = 1; 400746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 400846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa count = 0; 400946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 401046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa break; 401146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 401246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 401381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 401481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 4015f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 401681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 401700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 401800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 401900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 40204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 40214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 40229705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 40239705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori String[] selectionArgs) { 40249705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // update status_updates table, if status is provided 40259705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 40269705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori int updateCount = 0; 40279705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 40289705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 40295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro updateCount = mActiveDb.get().update(Tables.STATUS_UPDATES, 40309705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues, 40319705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori getWhereClauseForStatusUpdatesTable(selection), 40329705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 40339705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40349705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 40359705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // now update the Presence table 40369705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues = getSettableColumnsForPresenceTable(values); 40379705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 40385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro updateCount = mActiveDb.get().update(Tables.PRESENCE, settableValues, 40399705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selection, selectionArgs); 40409705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40419705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 40429705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // potentially get updated in this method. 40439705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return updateCount; 40449705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40459705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 40463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int updateStreamItems(Uri uri, ContentValues values, String selection, 40473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 40483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Stream items can't be moved to a new raw contact. 40493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.remove(StreamItems.RAW_CONTACT_ID); 40503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check that the stream items being updated belong to the account. 40523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 40533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItems(account, selection, selectionArgs); 40543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40556802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to update accounts params - they don't exist in the stream items table. 40566802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_NAME); 40576802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_TYPE); 40586802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 40593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If there's been no exception, the update should be fine. 40605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().update(Tables.STREAM_ITEMS, values, selection, selectionArgs); 40613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 40623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int updateStreamItemPhotos(Uri uri, ContentValues values, String selection, 40643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 40653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Stream item photos can't be moved to a new stream item. 40663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.remove(StreamItemPhotos.STREAM_ITEM_ID); 40673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check that the stream item photos being updated belong to the account. 40693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 40703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItemPhotos(account, selection, selectionArgs); 40713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40726802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to update accounts params - they don't exist in the stream item 40736802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // photos table. 40746802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_NAME); 40756802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_TYPE); 40766802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 40776802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Process the photo (since we're updating, it's valid for the photo to not be present). 40786802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (processStreamItemPhoto(values, true)) { 40796802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // If there's been no exception, the update should be fine. 40805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().update(Tables.STREAM_ITEM_PHOTOS, values, selection, 40815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 40826802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 40836802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return 0; 40843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 40853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40869705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 40879705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Build a where clause to select the rows to be updated in status_updates table. 40889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 40899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private String getWhereClauseForStatusUpdatesTable(String selection) { 40909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.setLength(0); 40919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 40929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(selection); 40939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(")"); 40949705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mSb.toString(); 40959705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40969705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 40979705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 40989705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 40999705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 41009705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS); 41019705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 41029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_TIMESTAMP); 41039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 41049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_RES_PACKAGE); 41059705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 41069705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_LABEL); 41079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 41089705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_ICON); 41099705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 41109705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 41119705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 41129705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 41139705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 41149705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 41159705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.PRESENCE); 4116aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.CHAT_CAPABILITY, values, 4117aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori StatusUpdates.CHAT_CAPABILITY); 41189705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 41199705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 41209705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 41215aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 4122f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 412373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 4124ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 4125ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 412673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 4127f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 412873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 412973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 413073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 413173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 413273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 413373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 413473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 413573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 41365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int count = mActiveDb.get().update(Tables.GROUPS, updatedValues, selectionWithId, 41375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 41381a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 41391a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 414094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 414143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 414243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // TODO: This will not work for groups that have a data set specified, since the content 414343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // resolver will not be able to request a sync for the right source (unless it is updated 414443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // to key off account with data set). 41456ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 41461129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 41475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 4148e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey Groups.ACCOUNT_TYPE}, selectionWithId, selectionArgs, null, 41496ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 41506ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 41516ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 41526ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 41536ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 41546ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 41556ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 415624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 41576ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 4158ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 41596ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 41606ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 41616ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 41626ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 41636ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 41646ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 41656ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 41666ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 416794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 416894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 416994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 4170b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 4171b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 41725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final int count = mActiveDb.get().update(Tables.SETTINGS, values, selection, selectionArgs); 41731a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 41741a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 4175e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4176e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 4177e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4178e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4179dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs, 4180dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 41814529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 41824529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 41834529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 41844529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 418573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 418697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 418797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 418897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0"); 418997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 419097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 41914529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 41925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(Views.RAW_CONTACTS, 419351bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 41944529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 41954529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 41964529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 41974529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 4198dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateRawContact(rawContactId, values, callerIsSyncAdapter); 41994529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 42004529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 42014529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 42024529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 42034529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 42044529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 42054529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 42064529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 42074529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 4208dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContact(long rawContactId, ContentValues values, 4209dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 421096b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker final String selection = RawContacts._ID + " = ?"; 421196b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(rawContactId); 421219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 421319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 421419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 4215ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = null; 4216ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = null; 421743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String dataSet = null; 421819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 42195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, 42205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection, mSelectionArgs1, null, null, null); 422119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 422219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 422319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 4224ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 4225ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 422643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro dataSet = cursor.getString(RawContactsQuery.DATA_SET); 422719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 422819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 422919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 423019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 423119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 423219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 423319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 4234f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 42355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int count = mActiveDb.get().update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1); 42365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 4237f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (values.containsKey(RawContacts.AGGREGATION_MODE)) { 4238f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = values.getAsInteger(RawContacts.AGGREGATION_MODE); 4239f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov 4240f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // As per ContactsContract documentation, changing aggregation mode 4241f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // to DEFAULT should not trigger aggregation 4242f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (aggregationMode != RawContacts.AGGREGATION_MODE_DEFAULT) { 42435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markForAggregation(rawContactId, aggregationMode, false); 4244f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 4245f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 4246433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 4247dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 4248dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 4249dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana values.getAsLong(RawContacts.STARRED) != 0); 4250dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 42515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateStarred(rawContactId); 4252dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 4253dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then update the 4254dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // favorites group membership based on whether or not this contact is starred. 4255dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // If it is starred, add a group membership, if one doesn't already exist 4256dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // otherwise delete any matching group memberships. 4257dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 42585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro boolean starred = 0 != DatabaseUtils.longForQuery(mActiveDb.get(), 4259dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana SELECTION_STARRED_FROM_RAW_CONTACTS, 4260dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}); 4261dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred); 4262dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4263dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4264dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 4265dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then add a 4266dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // group membership to the group marked as AutoAdd, if any. 4267dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 4268dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 4269433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 4270dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 4271285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 42725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateLookupKeyForRawContact(mActiveDb.get(), rawContactId); 4273285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 4274f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.containsKey(RawContacts.NAME_VERIFIED)) { 4275f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 4276f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // If setting NAME_VERIFIED for this raw contact, reset it for all 4277f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // other raw contacts in the same aggregate 4278f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.getAsInteger(RawContacts.NAME_VERIFIED) != 0) { 42795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().resetNameVerifiedForOtherRawContacts(rawContactId); 4280f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 42815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateDisplayNameForRawContact(mActiveDb.get(), rawContactId); 4282f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 428319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 42845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().rawContactInserted(rawContactId, 428543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new AccountWithDataSet(accountName, accountType, dataSet)); 428619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 42875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 428933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 429033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 4291321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 4292f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 429320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 429420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 429520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 42965ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 429720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 429820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 429920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 430020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 430120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 43025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(DataColumns.PACKAGE_ID, mDbHelper.get().getPackageId(packageName)); 430320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 430420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 430597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 430697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 430797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov Data.IS_READ_ONLY + "=0"); 430897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 430997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 4310653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 431120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4312653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 4313653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 43145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryLocal(uri, 4315f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro DataRowHandler.DataUpdateQuery.COLUMNS, 43165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection, selectionArgs, null, -1 /* directory ID */); 4317653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 4318653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 4319f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 432020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 4321653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 4322653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 432320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 432420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4325653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 432620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 432720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4328f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 4329653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 4330653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 4331321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 4332653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 4333f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final String mimeType = c.getString(DataRowHandler.DataUpdateQuery.MIMETYPE); 4334a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 4335f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro boolean updated = 43365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro rowHandler.update(mActiveDb.get(), mTransactionContext.get(), values, c, 43375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro callerIsSyncAdapter); 4338f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) { 4339f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS); 4340a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 4341f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return updated ? 1 : 0; 4342321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 4343321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 43448c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 4345dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 43468c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 43475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(Views.CONTACTS, 43485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[] { Contacts._ID }, selection, selectionArgs, null, null, null); 43498c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 43508c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 43518c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 435224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 4353dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateContactOptions(contactId, values, callerIsSyncAdapter); 43548c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 43558c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 43568c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 43578c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 43588c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 43598c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 43608c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 43618c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 43628c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 4363dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateContactOptions(long contactId, ContentValues values, 4364dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 4365d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 43668c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 4367b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 4368d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 4369b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 4370d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 4371b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 4372d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 4373b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 4374d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 4375b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 4376d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 4377d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 4378d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 43798c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 4380d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 4381d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 4382d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 43838c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 4384c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 43858c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 4386c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 4387c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 43884da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 43895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?" 439097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov + " AND " + RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0", mSelectionArgs1); 43918c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 4392dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (mValues.containsKey(RawContacts.STARRED) && !callerIsSyncAdapter) { 43935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(Views.RAW_CONTACTS, 4394dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[] { RawContacts._ID }, RawContacts.CONTACT_ID + "=?", 4395dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mSelectionArgs1, null, null, null); 4396dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 4397dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (cursor.moveToNext()) { 4398dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana long rawContactId = cursor.getLong(0); 4399dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 4400dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.getAsLong(RawContacts.STARRED) != 0); 4401dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4402dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 4403dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana cursor.close(); 4404dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4405dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4406dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 44078c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 44088c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 44098c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 4410b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 44118c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 4412b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 44138c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 4414b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 44158c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 4416b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 44178c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 4418b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 44198c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 44208c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 44215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int rslt = mActiveDb.get().update(Tables.CONTACTS, mValues, Contacts._ID + "=?", 44225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mSelectionArgs1); 44236e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori 44249b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori if (values.containsKey(Contacts.LAST_TIME_CONTACTED) && 44259b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori !values.containsKey(Contacts.TIMES_CONTACTED)) { 44265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 44275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 44289b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori } 44299b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori return rslt; 4430f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 4431d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 4432127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 4433127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 44340c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 44350c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 443680c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 4437ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov long rawContactId1; 4438ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov long rawContactId2; 44390c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 44400c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 44410c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 44420c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 44430c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 44440c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 4445b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4446127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 44470c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 44484da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[0] = String.valueOf(rawContactId1); 44494da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[1] = String.valueOf(rawContactId2); 44500c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 44514da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=? AND " 44524da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=?", mSelectionArgs2); 44530c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 44546bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 44556bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 44560c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 44570c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 44580c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 44590c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 4460127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 4461127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 44625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().invalidateAggregationExceptionCache(); 44635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markForAggregation(rawContactId1, 446469cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 44655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markForAggregation(rawContactId2, 446669cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 4467dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 44685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().aggregateContact(mTransactionContext.get(), db, rawContactId1); 44695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().aggregateContact(mTransactionContext.get(), db, rawContactId2); 4470127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 4471127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 4472127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 4473127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 4474b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4475b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 447670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 4477bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS); 44783826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 44793826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 4480bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected boolean updateAccountsInBackground(Account[] accounts) { 4481f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao // TODO : Check the unit test. 4482e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov boolean accountsChanged = false; 44835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mDbHelper.get().getWritableDatabase(); 44845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(db); 44855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.beginTransaction(); 448670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 448743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Set<AccountWithDataSet> existingAccountsWithDataSets = 448843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro findValidAccountsWithDataSets(Tables.ACCOUNTS); 4489743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov 449043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Add a row to the ACCOUNTS table (with no data set) for each new account. 4491743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov for (Account account : accounts) { 449243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro AccountWithDataSet accountWithDataSet = new AccountWithDataSet( 449343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro account.name, account.type, null); 449443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (!existingAccountsWithDataSets.contains(accountWithDataSet)) { 4495e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 449643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 449743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Add an account entry with an empty data set to match the account. 44985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 449943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ", " + RawContacts.ACCOUNT_TYPE + ", " + RawContacts.DATA_SET 450043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ") VALUES (?, ?, ?)", 450143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new String[] { 450243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 450343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType(), 450443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getDataSet() 450543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }); 4506743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 4507743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 450848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 450943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Check each of the existing sub-accounts against the account list. If the owning 451043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // account no longer exists, the sub-account and all its data should be deleted. 451143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro List<AccountWithDataSet> accountsWithDataSetsToDelete = 451243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new ArrayList<AccountWithDataSet>(); 451343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro List<Account> accountList = Arrays.asList(accounts); 451443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro for (AccountWithDataSet accountWithDataSet : existingAccountsWithDataSets) { 451543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Account owningAccount = new Account( 451643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), accountWithDataSet.getAccountType()); 451743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (!accountList.contains(owningAccount)) { 451843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountsWithDataSetsToDelete.add(accountWithDataSet); 451943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 452070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 452170d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 452243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (!accountsWithDataSetsToDelete.isEmpty()) { 4523e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 452443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro for (AccountWithDataSet accountWithDataSet : accountsWithDataSetsToDelete) { 452543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Log.d(TAG, "removing data for removed account " + accountWithDataSet); 452643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String[] accountParams = new String[] { 452743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 452843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType() 452943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }; 453043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String[] accountWithDataSetParams = accountWithDataSet.getDataSet() == null 453143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ? accountParams 453243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro : new String[] { 453343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 453443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType(), 453543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getDataSet() 453643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }; 453743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String groupsDataSetClause = " AND " + Groups.DATA_SET 453843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + (accountWithDataSet.getDataSet() == null ? " IS NULL" : " = ?"); 453943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String rawContactsDataSetClause = " AND " + RawContacts.DATA_SET 454043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + (accountWithDataSet.getDataSet() == null ? " IS NULL" : " = ?"); 4541f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro String settingsDataSetClause = " AND " + Settings.DATA_SET 4542f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro + (accountWithDataSet.getDataSet() == null ? " IS NULL" : " = ?"); 454343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 45445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4545e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.GROUPS + 4546e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 454743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + Groups.ACCOUNT_TYPE + " = ?" + 454843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro groupsDataSetClause, accountWithDataSetParams); 45495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4550e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 4551e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 4552e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "SELECT " + RawContacts._ID + 4553e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 4554e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 455543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 455643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactsDataSetClause + ")", accountWithDataSetParams); 45575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4558c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "DELETE FROM " + Tables.STREAM_ITEM_PHOTOS + 4559c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + StreamItemPhotos.STREAM_ITEM_ID + " IN (" + 4560c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "SELECT " + StreamItems._ID + 4561c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " FROM " + Tables.STREAM_ITEMS + 4562c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + StreamItems.RAW_CONTACT_ID + " IN (" + 4563c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "SELECT " + RawContacts._ID + 4564c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " FROM " + Tables.RAW_CONTACTS + 4565c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 4566c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 4567c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro rawContactsDataSetClause + "))", 4568c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro accountWithDataSetParams); 4569c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro db.execSQL( 4570c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "DELETE FROM " + Tables.STREAM_ITEMS + 4571c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + StreamItems.RAW_CONTACT_ID + " IN (" + 4572c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "SELECT " + RawContacts._ID + 4573c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " FROM " + Tables.RAW_CONTACTS + 4574c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 4575c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 4576c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro rawContactsDataSetClause + ")", 4577c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro accountWithDataSetParams); 4578c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro db.execSQL( 4579e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.RAW_CONTACTS + 4580e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 458143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 458243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactsDataSetClause, accountWithDataSetParams); 45835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4584e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 4585e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 4586f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro " AND " + Settings.ACCOUNT_TYPE + " = ?" + 4587f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro settingsDataSetClause, accountWithDataSetParams); 45885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4589e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.ACCOUNTS + 4590e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + "=?" + 459143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + "=?" + 459243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactsDataSetClause, accountWithDataSetParams); 45935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4594d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov "DELETE FROM " + Tables.DIRECTORIES + 4595d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov " WHERE " + Directory.ACCOUNT_NAME + "=?" + 459643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + Directory.ACCOUNT_TYPE + "=?", accountParams); 45974458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov resetDirectoryCache(); 4598e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 4599e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov 460033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // Find all aggregated contacts that used to contain the raw contacts 460133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // we have just deleted and see if they are still referencing the deleted 4602e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov // names or photos. If so, fix up those contacts. 460333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov HashSet<Long> orphanContactIds = Sets.newHashSet(); 46045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = db.rawQuery("SELECT " + Contacts._ID + 460533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " FROM " + Tables.CONTACTS + 460633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " WHERE (" + Contacts.NAME_RAW_CONTACT_ID + " NOT NULL AND " + 460769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov Contacts.NAME_RAW_CONTACT_ID + " NOT IN " + 460869cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + RawContacts._ID + 460969cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + "))" + 461033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " OR (" + Contacts.PHOTO_ID + " NOT NULL AND " + 461133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Contacts.PHOTO_ID + " NOT IN " + 461269cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + Data._ID + 461369cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.DATA + "))", null); 461433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov try { 461533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov while (cursor.moveToNext()) { 461633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov orphanContactIds.add(cursor.getLong(0)); 461733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 461833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } finally { 461933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov cursor.close(); 462033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 462133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 462233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov for (Long contactId : orphanContactIds) { 46235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateAggregateData(mTransactionContext.get(), contactId); 462433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 46255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().updateAllVisible(); 4626bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 462733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 462833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 462943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Now that we've done the account-based additions and subtractions from the Accounts 463043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // table, check for raw contacts that have been added with a data set and add Accounts 463143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // entries for those if necessary. 463243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro existingAccountsWithDataSets = findValidAccountsWithDataSets(Tables.ACCOUNTS); 463343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Set<AccountWithDataSet> rawContactAccountsWithDataSets = 463443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro findValidAccountsWithDataSets(Tables.RAW_CONTACTS); 463543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactAccountsWithDataSets.removeAll(existingAccountsWithDataSets); 463643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 463743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Any remaining raw contact sub-accounts need to be added to the Accounts table. 463843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro for (AccountWithDataSet accountWithDataSet : rawContactAccountsWithDataSets) { 463943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountsChanged = true; 464043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 464143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Add an account entry to match the raw contact. 46425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 464343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ", " + RawContacts.ACCOUNT_TYPE + ", " + RawContacts.DATA_SET 464443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ") VALUES (?, ?, ?)", 464543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new String[] { 464643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 464743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType(), 464843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getDataSet() 464943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }); 465043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 465143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 4652e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov if (accountsChanged) { 465343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // TODO: Should sync state take data set into consideration? 46545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getSyncState().onAccountsChanged(db, accounts); 4655e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 46565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.setTransactionSuccessful(); 465770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 46585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.endTransaction(); 465970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 466073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.clear(); 46613826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 46623826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (accountsChanged) { 46633826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateContactsAccountCount(accounts); 46643826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateProviderStatus(); 46653826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46663826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 4667afb84050536a4472c13efc0e996d31132d254605Dmitri Plotnikov return accountsChanged; 466870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 4669619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 46703826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private void updateContactsAccountCount(Account[] accounts) { 46713826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov int count = 0; 46723826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov for (Account account : accounts) { 46733826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (isContactsAccount(account)) { 46743826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov count++; 46753826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46763826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46773826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mContactsAccountCount = count; 46783826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46793826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 46803826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov protected boolean isContactsAccount(Account account) { 46813826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov final IContentService cs = ContentResolver.getContentService(); 46823826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov try { 46833826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return cs.getIsSyncable(account, ContactsContract.AUTHORITY) > 0; 46843826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } catch (RemoteException e) { 46853826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov Log.e(TAG, "Cannot obtain sync flag for account: " + account, e); 46863826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return false; 46873826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46883826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46893826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 469072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void onPackageChanged(String packageName) { 4691bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_DIRECTORIES, packageName); 4692d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4693d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4694619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 469543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * Finds all distinct account types and data sets present in the specified table. 4696627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov */ 469743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro private Set<AccountWithDataSet> findValidAccountsWithDataSets(String table) { 469843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Set<AccountWithDataSet> accountsWithDataSets = new HashSet<AccountWithDataSet>(); 46995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().rawQuery( 470043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro "SELECT DISTINCT " + RawContacts.ACCOUNT_NAME + "," + RawContacts.ACCOUNT_TYPE + 470143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro "," + RawContacts.DATA_SET + 470243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " FROM " + table, null); 4703627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 4704627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov while (c.moveToNext()) { 470591abbc9f691297594262d1f2d79acb744a66712cDave Santoro if (!c.isNull(0) && !c.isNull(1)) { 470643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountsWithDataSets.add( 470743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new AccountWithDataSet(c.getString(0), c.getString(1), c.getString(2))); 4708627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4709627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4710627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } finally { 4711627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c.close(); 4712627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 471343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro return accountsWithDataSets; 4714627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4715627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 47164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 47174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 47184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 471915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 472015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mReadAccessLatch); 472115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 47225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Query the profile DB if appropriate. 47235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 47245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 47255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileProvider.query(uri, projection, selection, selectionArgs, sortOrder); 47265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 47275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 47285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Otherwise proceed with a normal query against the contacts DB. 47295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 47305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mContactsHelper.getReadableDatabase()); 4731d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String directory = getQueryParameter(uri, ContactsContract.DIRECTORY_PARAM_KEY); 4732385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov if (directory == null) { 4733b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return addSnippetExtrasToCursor(uri, 47345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, -1)); 4735385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } else if (directory.equals("0")) { 4736b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return addSnippetExtrasToCursor(uri, 47373716f1447ceb21180d1301790eabd8b9453f486dDave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, 47385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Directory.DEFAULT)); 4739d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } else if (directory.equals("1")) { 4740b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return addSnippetExtrasToCursor(uri, 47413716f1447ceb21180d1301790eabd8b9453f486dDave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, 47425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Directory.LOCAL_INVISIBLE)); 4743d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4744d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4745d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov DirectoryInfo directoryInfo = getDirectoryAuthority(directory); 4746d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo == null) { 4747a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov Log.e(TAG, "Invalid directory ID: " + uri); 4748a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov return null; 4749d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4750d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4751d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Builder builder = new Uri.Builder(); 4752d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.scheme(ContentResolver.SCHEME_CONTENT); 4753d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.authority(directoryInfo.authority); 4754d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.encodedPath(uri.getEncodedPath()); 4755d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountName != null) { 4756d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, directoryInfo.accountName); 4757d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4758d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountType != null) { 4759d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, directoryInfo.accountType); 4760d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 47612e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 47622e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov String limit = getLimit(uri); 47632e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov if (limit != null) { 47642e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov builder.appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, limit); 47652e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov } 47662e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 4767d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Uri directoryUri = builder.build(); 476809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 476909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov if (projection == null) { 477009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov projection = getDefaultProjection(uri); 477109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 477209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 4773332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov Cursor cursor = getContext().getContentResolver().query(directoryUri, projection, selection, 4774d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov selectionArgs, sortOrder); 47756ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 47766ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (cursor == null) { 47776ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return null; 47786ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 47796ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 4780547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro CrossProcessCursor crossProcessCursor = getCrossProcessCursor(cursor); 4781547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro if (crossProcessCursor != null) { 4782b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return addSnippetExtrasToCursor(uri, cursor); 4783547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } else { 4784b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return matrixCursorFromCursor(addSnippetExtrasToCursor(uri, cursor)); 4785547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } 47863716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 47873716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 4788b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private Cursor addSnippetExtrasToCursor(Uri uri, Cursor cursor) { 4789547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro 4790547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro // If the cursor doesn't contain a snippet column, don't bother wrapping it. 4791547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro if (cursor.getColumnIndex(SearchSnippetColumns.SNIPPET) < 0) { 4792b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return cursor; 4793547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } 4794547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro 47953716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Parse out snippet arguments for use when snippets are retrieved from the cursor. 47963716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String[] args = null; 47973716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String snippetArgs = 47983716f1447ceb21180d1301790eabd8b9453f486dDave Santoro getQueryParameter(uri, SearchSnippetColumns.SNIPPET_ARGS_PARAM_KEY); 47993716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (snippetArgs != null) { 48003716f1447ceb21180d1301790eabd8b9453f486dDave Santoro args = snippetArgs.split(","); 48013716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 48023716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 48033716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String query = uri.getLastPathSegment(); 48043716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String startMatch = args != null && args.length > 0 ? args[0] 48053716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_START_MATCH; 48063716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String endMatch = args != null && args.length > 1 ? args[1] 48073716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_END_MATCH; 48083716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String ellipsis = args != null && args.length > 2 ? args[2] 48093716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_ELLIPSIS; 48103716f1447ceb21180d1301790eabd8b9453f486dDave Santoro int maxTokens = args != null && args.length > 3 ? Integer.parseInt(args[3]) 48113716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_MAX_TOKENS; 48123716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 4813b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson // Snippet data is needed for the snippeting on the client side, so store it in the cursor 4814b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (cursor instanceof AbstractCursor && deferredSnippetingRequested(uri)){ 4815b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson Bundle oldExtras = cursor.getExtras(); 4816b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson Bundle extras = new Bundle(); 4817b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (oldExtras != null) { 4818b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson extras.putAll(oldExtras); 4819b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 4820b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson extras.putString(ContactsContract.DEFERRED_SNIPPETING_QUERY, query); 4821b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 4822b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson ((AbstractCursor) cursor).setExtras(extras); 48235517770250b3afa4fd88b6869c3244680821d222Dave Santoro } 4824b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return cursor; 4825b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 4826b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 4827b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private Cursor addDeferredSnippetingExtra(Cursor cursor) { 4828b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (cursor instanceof AbstractCursor){ 4829b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson Bundle oldExtras = cursor.getExtras(); 4830b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson Bundle extras = new Bundle(); 4831b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (oldExtras != null) { 4832b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson extras.putAll(oldExtras); 4833b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 4834b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson extras.putBoolean(ContactsContract.DEFERRED_SNIPPETING, true); 4835b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson ((AbstractCursor) cursor).setExtras(extras); 4836b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 4837b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return cursor; 48386ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 48396ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 48406ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov private CrossProcessCursor getCrossProcessCursor(Cursor cursor) { 48416ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov Cursor c = cursor; 48426ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (c instanceof CrossProcessCursor) { 48436ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return (CrossProcessCursor) c; 48446ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } else if (c instanceof CursorWindow) { 48456ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return getCrossProcessCursor(((CursorWrapper) c).getWrappedCursor()); 48466ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } else { 48476ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return null; 48486ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 48496ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 48506ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 48516ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov public MatrixCursor matrixCursorFromCursor(Cursor cursor) { 48526ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames()); 48536ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov int numColumns = cursor.getColumnCount(); 48546ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov String data[] = new String[numColumns]; 48556ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov cursor.moveToPosition(-1); 48566ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov while (cursor.moveToNext()) { 48576ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov for (int i = 0; i < numColumns; i++) { 48586ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov data[i] = cursor.getString(i); 48596ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 48606ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov newCursor.addRow(data); 4861332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov } 48626ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return newCursor; 4863d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4864d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4865d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final class DirectoryQuery { 4866d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 4867d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory._ID, 4868d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.DIRECTORY_AUTHORITY, 4869d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_NAME, 4870d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_TYPE 4871d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov }; 4872d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4873d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int DIRECTORY_ID = 0; 4874d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int AUTHORITY = 1; 4875d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_NAME = 2; 4876d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_TYPE = 3; 4877d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4878d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4879d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 4880d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Reads and caches directory information for the database. 4881d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 4882d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private DirectoryInfo getDirectoryAuthority(String directoryId) { 48834458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov synchronized (mDirectoryCache) { 48844458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov if (!mDirectoryCacheValid) { 48854458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCache.clear(); 48865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mDbHelper.get().getReadableDatabase(); 488749d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov Cursor cursor = db.query(Tables.DIRECTORIES, 48884458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DirectoryQuery.COLUMNS, 48894458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov null, null, null, null, null); 48904458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov try { 48914458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov while (cursor.moveToNext()) { 48924458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DirectoryInfo info = new DirectoryInfo(); 48934458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov String id = cursor.getString(DirectoryQuery.DIRECTORY_ID); 48944458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.authority = cursor.getString(DirectoryQuery.AUTHORITY); 48954458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.accountName = cursor.getString(DirectoryQuery.ACCOUNT_NAME); 48964458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.accountType = cursor.getString(DirectoryQuery.ACCOUNT_TYPE); 48974458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCache.put(id, info); 48984458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 48994458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } finally { 49004458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov cursor.close(); 4901d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 49024458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCacheValid = true; 4903d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4904d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 49054458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov return mDirectoryCache.get(directoryId); 49064458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 4907d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4908d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 490972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void resetDirectoryCache() { 49104458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov synchronized(mDirectoryCache) { 49114458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCacheValid = false; 49124458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 491372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 491472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 49155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro protected Cursor queryLocal(Uri uri, String[] projection, String selection, 49165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String[] selectionArgs, String sortOrder, long directoryId) { 4917bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 4918bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 4919bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 49200b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 49215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 49225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 49235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 49245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 492535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4926d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 49271f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 4928c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 4929b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson boolean snippetDeferred = false; 4930c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 49312ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // The expression used in bundleLetterCountExtras() to get count. 49322ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki String addressBookIndexerCountExpression = null; 49332ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 4934a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 49354f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 493635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 49375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 49385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().query(mActiveDb.get(), projection, selection, 49395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs, sortOrder); 494035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4941d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 4942763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 49434b64b6e8f448938434cb1e022a4e7dfaae8f9c8cMakoto Onuki appendLocalDirectorySelectionIfNeeded(qb, directoryId); 4944619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 4945619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4946619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4947d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 49484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 4949763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 49504da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 49514da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 49526bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 49536bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 49546bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 49555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 49565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 49575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 49585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 49595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 49605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 4961fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 49625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 4963a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 49645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 49655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 49665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 49675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 4968763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 4969a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 49705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 4971a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 4972a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey); 4973a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 49745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 49755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4978763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 49794da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 49805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String.valueOf(lookupContactIdByLookupKey(mActiveDb.get(), lookupKey))); 49814da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 49825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 49835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49852149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov case CONTACTS_LOOKUP_DATA: 4986bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_ID_DATA: 4987bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_PHOTO: 4988bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_ID_PHOTO: { 49892149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 49902149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov int segmentCount = pathSegments.size(); 49912149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount < 4) { 49925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 49932149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov "Missing a lookup key", uri)); 49942149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 49952149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov String lookupKey = pathSegments.get(2); 49962149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount == 5) { 49972149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 49982149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 49992149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(lookupQb, uri, projection, false); 5000bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro if (match == CONTACTS_LOOKUP_PHOTO || match == CONTACTS_LOOKUP_ID_PHOTO) { 5001bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 5002bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } 5003a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 50045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 5005a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 5006a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.CONTACT_ID, contactId, Data.LOOKUP_KEY, lookupKey); 5007a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 50082149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov return c; 50092149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 50102149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 50112149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov // TODO see if the contact exists but has no data rows (rare) 50122149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 50132149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 50142149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 50155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 50162149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 501724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro String.valueOf(contactId)); 5018bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro if (match == CONTACTS_LOOKUP_PHOTO || match == CONTACTS_LOOKUP_ID_PHOTO) { 5019bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 5020bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } 50212149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov qb.appendWhere(" AND " + Data.CONTACT_ID + "=?"); 50222149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov break; 50232149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 50242149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 50253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_ID_STREAM_ITEMS: { 50263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long contactId = Long.parseLong(uri.getPathSegments().get(1)); 50273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 50283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 5029af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann qb.appendWhere(StreamItems.CONTACT_ID + "=?"); 50303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 50313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 50323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 50333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_LOOKUP_STREAM_ITEMS: 50343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_LOOKUP_ID_STREAM_ITEMS: { 50353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<String> pathSegments = uri.getPathSegments(); 50363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann int segmentCount = pathSegments.size(); 50373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (segmentCount < 4) { 50385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 50393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann "Missing a lookup key", uri)); 50403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 50413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String lookupKey = pathSegments.get(2); 50423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (segmentCount == 5) { 50433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long contactId = Long.parseLong(pathSegments.get(3)); 50443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 50453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(lookupQb); 50465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 50473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann projection, selection, selectionArgs, sortOrder, groupBy, limit, 5048af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann StreamItems.CONTACT_ID, contactId, 5049af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann StreamItems.CONTACT_LOOKUP_KEY, lookupKey); 50503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (c != null) { 50513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return c; 50523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 50533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 50543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 50553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 50565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 50573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 50583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(RawContacts.CONTACT_ID + "=?"); 50593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 50603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 50613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 5062f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 506342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 50645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 5065ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 5066f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 50674da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 506824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro String.valueOf(contactId)); 50694da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 5070f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 5071f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 5072f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 507342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 507442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); 507542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann String currentDateString = dateFormat.format(new Date()).toString(); 50765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().rawQuery( 507742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann "SELECT" + 507842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " 'vcards_' || ? || '.vcf' AS " + OpenableColumns.DISPLAY_NAME + "," + 507942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " NULL AS " + OpenableColumns.SIZE, 508042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann new String[] { currentDateString }); 508142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 508242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 5083ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 5084916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String filterParam = ""; 5085b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson boolean deferredSnipRequested = deferredSnippetingRequested(uri); 5086ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 5087916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov filterParam = uri.getLastPathSegment(); 5088ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 50897ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov setTablesAndProjectionMapForContactsWithSnippet( 5090b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson qb, uri, projection, filterParam, directoryId, 5091b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson deferredSnipRequested); 5092b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson snippetDeferred = isSingleWordQuery(filterParam) && 5093b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson deferredSnipRequested && snippetNeeded(projection); 5094ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5095ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5096ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 5097ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 5098ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 50992f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Basically the resultant SQL should look like this: 51002f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // (SQL for listing starred items) 51012f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // UNION ALL 51022f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // (SQL for listing frequently contacted items) 51032f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // ORDER BY ... 51042f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 51052f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final boolean phoneOnly = readBooleanQueryParameter( 51062f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa uri, ContactsContract.STREQUENT_PHONE_ONLY, false); 51072f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (match == CONTACTS_STREQUENT_FILTER && uri.getPathSegments().size() > 3) { 51084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 51094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5110e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 51115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 51122f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa selection = DbQueryUtils.concatenateClauses(selection, sb.toString()); 51134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 51144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 51152f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa String[] subProjection = null; 51165e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 51172f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa subProjection = appendProjectionArg(projection, TIMES_USED_SORT_COLUMN); 51185e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 51195e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 51204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 51214928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, false); 51224928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setProjectionMap(phoneOnly ? 51234928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa sStrequentPhoneOnlyStarredProjectionMap 51244928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa : sStrequentStarredProjectionMap); 51259dbfd650ccf93714f3266e80f9fbdbcb526ae7b3Daisuke Miyakawa if (phoneOnly) { 51265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro qb.appendWhere(DbQueryUtils.concatenateClauses( 51275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection, Contacts.HAS_PHONE_NUMBER + "=1")); 51289dbfd650ccf93714f3266e80f9fbdbcb526ae7b3Daisuke Miyakawa } 51292f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.setStrict(true); 51302f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final String starredQuery = qb.buildQuery(subProjection, 513124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Contacts.STARRED + "=1", Contacts._ID, null, null, null); 5132d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 51332f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Reset the builder. 5134d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 51352f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.setStrict(true); 51364928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 51374928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // Build the second query for frequent part. 51384928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa final String frequentQuery; 51394928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa if (phoneOnly) { 51404928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa final StringBuilder tableBuilder = new StringBuilder(); 51414928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // In phone only mode, we need to look at view_data instead of 51424928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // contacts/raw_contacts to obtain actual phone numbers. One problem is that 51434928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // view_data is much larger than view_contacts, so our query might become much 51444928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // slower. 51454928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // 51464928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // To avoid the possible slow down, we start from data usage table and join 51474928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // view_data to the table, assuming data usage table is quite smaller than 51484928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // data rows (almost always it should be), and we don't want any phone 51494928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // numbers not used by the user. This way sqlite is able to drop a number of 51504928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // rows in view_data in the early stage of data lookup. 51514928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa tableBuilder.append(Tables.DATA_USAGE_STAT 51524928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + " INNER JOIN " + Views.DATA + " " + Tables.DATA 51534928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + " ON (" + DataUsageStatColumns.CONCRETE_DATA_ID + "=" 51544928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + DataColumns.CONCRETE_ID + " AND " 51554928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + DataUsageStatColumns.CONCRETE_USAGE_TYPE + "=" 51564928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + DataUsageStatColumns.USAGE_TYPE_INT_CALL + ")"); 51574928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa appendContactPresenceJoin(tableBuilder, projection, RawContacts.CONTACT_ID); 51584928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa appendContactStatusUpdateJoin(tableBuilder, projection, 51594928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa ContactsColumns.LAST_STATUS_UPDATE_ID); 51604928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 51614928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setTables(tableBuilder.toString()); 51624928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setProjectionMap(sStrequentPhoneOnlyFrequentProjectionMap); 51634928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.appendWhere(DbQueryUtils.concatenateClauses( 51644928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa selection, 51654928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa Contacts.STARRED + "=0 OR " + Contacts.STARRED + " IS NULL", 51664928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa MimetypesColumns.MIMETYPE + " IN (" 51674928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + "'" + Phone.CONTENT_ITEM_TYPE + "', " 51684928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + "'" + SipAddress.CONTENT_ITEM_TYPE + "')")); 51694928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa frequentQuery = qb.buildQuery(subProjection, null, null, null, null, null); 51704928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa } else { 51714928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, true); 51724928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setProjectionMap(sStrequentFrequentProjectionMap); 51734928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.appendWhere(DbQueryUtils.concatenateClauses( 51744928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa selection, 51755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro "(" + Contacts.STARRED + " =0 OR " + Contacts.STARRED + " IS NULL)")); 51764928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa frequentQuery = qb.buildQuery(subProjection, 51774928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa null, Contacts._ID, null, null, null); 51784928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa } 5179d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 5180d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 51812f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final String unionQuery = 51822f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 51832f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa STREQUENT_ORDER_BY, STREQUENT_LIMIT); 51842f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 51852f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Here, we need to use selection / selectionArgs (supplied from users) "twice", 51862f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // as we want them both for starred items and for frequently contacted items. 51872f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // 51882f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // e.g. if the user specify selection = "starred =?" and selectionArgs = "0", 51892f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // the resultant SQL should be like: 51902f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // SELECT ... WHERE starred =? AND ... 51912f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // UNION ALL 51922f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // SELECT ... WHERE starred =? AND ... 51932f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa String[] doubledSelectionArgs = null; 51942f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (selectionArgs != null) { 51952f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final int length = selectionArgs.length; 51962f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa doubledSelectionArgs = new String[length * 2]; 51977d7d0e95636344c01eb4e4d034791c199bee98e9Daisuke Miyakawa System.arraycopy(selectionArgs, 0, doubledSelectionArgs, 0, length); 51987d7d0e95636344c01eb4e4d034791c199bee98e9Daisuke Miyakawa System.arraycopy(selectionArgs, 0, doubledSelectionArgs, length, length); 51992f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 52002f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 52015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().rawQuery(unionQuery, doubledSelectionArgs); 52022f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (cursor != null) { 52032f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa cursor.setNotificationUri(getContext().getContentResolver(), 5204d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 5205d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 52062f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa return cursor; 5207d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 5208d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 520945ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa case CONTACTS_FREQUENT: { 521045ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, true); 521145ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa qb.setProjectionMap(sStrequentFrequentProjectionMap); 521245ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa groupBy = Contacts._ID; 521345ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa if (!TextUtils.isEmpty(sortOrder)) { 521445ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa sortOrder = FREQUENT_ORDER_BY + ", " + sortOrder; 521545ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa } else { 521645ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa sortOrder = FREQUENT_ORDER_BY; 521745ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa } 521845ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa break; 521945ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa } 522045ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa 5221ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 5222763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 5223b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 522471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 52257cf50494501938f175d288077145acf49da8f171Daniel Lehmann String groupMimeTypeId = String.valueOf( 52267cf50494501938f175d288077145acf49da8f171Daniel Lehmann mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 52274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 52287cf50494501938f175d288077145acf49da8f171Daniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, groupMimeTypeId); 5229b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5230b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 5231b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5232b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 523324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: { 523424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForContacts(qb, uri, projection); 523524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 523624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 523724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 523824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_ENTITIES: { 523924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForEntities(qb, uri, projection); 524024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 524124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 524224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 524324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: { 5244ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 524524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.setProjectionMap(sContactsVCardProjectionMap); 524624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 524724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 524824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 5249a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_DATA: { 52504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 525182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 52524da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 52534da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 52546bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 52556bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 525600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 5257a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 52583653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 525982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 52604da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 52614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 52623653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 52633653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 52643653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 52653653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 5266a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_ENTITIES: { 5267a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 5268a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 5269a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 5270a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 5271a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 5272a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5273a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5274a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ENTITIES: 5275a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ID_ENTITIES: { 5276a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 5277a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov int segmentCount = pathSegments.size(); 5278a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount < 4) { 52795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 5280a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov "Missing a lookup key", uri)); 5281a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5282a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lookupKey = pathSegments.get(2); 5283a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount == 5) { 5284a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 5285a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 5286a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(lookupQb, uri, projection); 5287a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 5288a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 52895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 5290a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 5291a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.CONTACT_ID, contactId, 5292a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.LOOKUP_KEY, lookupKey); 5293a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 5294a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 5295a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5296a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5297a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5298a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 5299a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 53005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String.valueOf(lookupContactIdByLookupKey(mActiveDb.get(), lookupKey))); 5301a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + Contacts.Entity.CONTACT_ID + "=?"); 5302a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 5303a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5304a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 53053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 53063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 53073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 53083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 53103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 53113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 53123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 53139b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann qb.appendWhere(StreamItems._ID + "=?"); 53143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 53153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 53173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_LIMIT: { 53186802030a777c0c3ba1dc029c534cca4784260632Dave Santoro MatrixCursor cursor = new MatrixCursor(new String[]{StreamItems.MAX_ITEMS}, 1); 53196802030a777c0c3ba1dc029c534cca4784260632Dave Santoro cursor.addRow(new Object[]{MAX_STREAM_ITEMS_PER_RAW_CONTACT}); 53203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return cursor; 53213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 53233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 53243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 53253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 53263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 53283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 53293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 53303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 53313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemId); 53323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=?"); 53333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 53343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 53363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 53373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 53383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 53393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 53403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemPhotoId); 53413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemId); 53423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=? AND " + 53433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=?"); 53443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 53453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 53463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 5347f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case PHOTO_DIMENSIONS: { 5348f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro MatrixCursor cursor = new MatrixCursor( 5349f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro new String[]{DisplayPhoto.DISPLAY_MAX_DIM, DisplayPhoto.THUMBNAIL_MAX_DIM}, 5350f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1); 5351f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro cursor.addRow(new Object[]{mMaxDisplayPhotoDim, mMaxThumbnailPhotoDim}); 5352f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return cursor; 5353f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 5354f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 53554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 535682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 53577cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + "=" + 53587cf50494501938f175d288077145acf49da8f171Daniel Lehmann mDbHelper.get().getMimeTypeIdForPhone()); 53592ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 53602ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // Dedupe phone numbers per contact. 5361cf55cbe8932f620484a3634d13ecc116c32fdc99Daisuke Miyakawa groupBy = RawContacts.CONTACT_ID + ", " + Data.DATA1; 53622ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 53632ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // In this case, because we dedupe phone numbers, the address book indexer needs 53642ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // to take it into account too. (Otherwise headers will appear in wrong positions.) 53652ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // So use count(distinct pair(CONTACT_ID, PHONE NUMBER)) instead of count(*). 53662ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // But because there's no such thing as pair() on sqlite, we use 53672ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // CONTACT_ID || ',' || PHONE NUMBER instead. 53682ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // This only slows down the query by 14% with 10,000 contacts. 53692ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki addressBookIndexerCountExpression = "DISTINCT " 53702ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki + RawContacts.CONTACT_ID + "||','||" + Data.DATA1; 53712815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 53722815f58f72f109790585931f601a63ddc02536a5Evan Millar } 53732815f58f72f109790585931f601a63ddc02536a5Evan Millar 537448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 537582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 53764da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 53777cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 53787cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForPhone()); 53794da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 538048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 538148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 538248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 5383ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 538446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String typeParam = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 538546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Integer typeInt = sDataUsageTypeMap.get(typeParam); 538646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (typeInt == null) { 538746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa typeInt = DataUsageStatColumns.USAGE_TYPE_INT_CALL; 538846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 538946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, true, typeInt); 53907cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 53917cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForPhone()); 5392ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 53934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 53944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5395a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 53965e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 539745d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov boolean hasCondition = false; 53985e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 53995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 54005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 5401155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN " + 5402155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov "(SELECT " + RawContactsColumns.CONCRETE_ID + 5403155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.SEARCH_INDEX + 5404155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 5405155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " ON (" + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID 5406155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov + "=" + RawContactsColumns.CONCRETE_CONTACT_ID + ")" + 5407155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " WHERE " + SearchIndexColumns.NAME + " MATCH "); 54082352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, sanitizeMatch(filterParam) + "*"); 5409155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(")"); 54105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 541145d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 54125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 5414892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String number = PhoneNumberUtils.normalizeNumber(filterParam); 5415892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (!TextUtils.isEmpty(number)) { 54165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 54175e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 54185e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54195e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 5420892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov " IN (SELECT DISTINCT " + PhoneLookupColumns.DATA_ID 5421892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 5422892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 5423892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append(number); 5424892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append("%')"); 542545d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 542645d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov } 542745d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov 542845d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov if (!hasCondition) { 542945d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // If it is neither a phone number nor a name, the query should return 543045d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // an empty cursor. Let's ensure that. 543145d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov sb.append("0"); 54325e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54335e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 5434a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 5435ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 543658567abca253f1efa2db5c39e17e42dca589e916Daisuke Miyakawa groupBy = "(CASE WHEN " + PhoneColumns.NORMALIZED_NUMBER 543758567abca253f1efa2db5c39e17e42dca589e916Daisuke Miyakawa + " IS NOT NULL THEN " + PhoneColumns.NORMALIZED_NUMBER 543858567abca253f1efa2db5c39e17e42dca589e916Daisuke Miyakawa + " ELSE " + Phone.NUMBER + " END), " + RawContacts.CONTACT_ID; 5439a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 544046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String accountPromotionSortOrder = getAccountPromotionSortOrder(uri); 544146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(accountPromotionSortOrder)) { 544246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = accountPromotionSortOrder + ", " + PHONE_FILTER_SORT_ORDER; 544346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 544446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = PHONE_FILTER_SORT_ORDER; 544546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 5446a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 5447ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5448ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5449ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 54504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 545182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 54527cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 54537cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForEmail()); 54544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 54554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 54564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 545748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 545882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 54594da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 54607cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 54617cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForEmail() 54624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + Data._ID + "=?"); 546348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 546448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 546548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 54665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 546782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 54687cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 54697cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForEmail()); 54704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 547108768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String email = uri.getLastPathSegment(); 54725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String address = mDbHelper.get().extractAddressFromEmailAddress(email); 547308768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, address); 547408768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov qb.appendWhere(" AND UPPER(" + Email.DATA + ")=UPPER(?)"); 54754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 5476ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5477ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5478ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 54795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 548046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String typeParam = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 548146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Integer typeInt = sDataUsageTypeMap.get(typeParam); 548246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (typeInt == null) { 548346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa typeInt = DataUsageStatColumns.USAGE_TYPE_INT_LONG_TEXT; 548446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 548546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, true, typeInt); 548607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov String filterParam = null; 54877d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa 548807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 548907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = uri.getLastPathSegment(); 549007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (TextUtils.isEmpty(filterParam)) { 549107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = null; 549207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 549307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 54945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 549507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterParam == null) { 549607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // If the filter is unspecified, return nothing 549707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(" AND 0"); 549807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } else { 549907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 550007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append(" AND " + Data._ID + " IN ("); 550107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 550207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov "SELECT " + Data._ID + 550307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 55042a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "="); 55055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro sb.append(mDbHelper.get().getMimeTypeIdForEmail()); 55062a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov sb.append(" AND " + Data.DATA1 + " LIKE "); 550707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, filterParam + '%'); 550820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 5509155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append( 5510155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " UNION SELECT " + Data._ID + 5511155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.DATA + 5512155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " WHERE +" + DataColumns.MIMETYPE_ID + "="); 55135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro sb.append(mDbHelper.get().getMimeTypeIdForEmail()); 5514155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(" AND " + Data.RAW_CONTACT_ID + " IN " + 5515155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov "(SELECT " + RawContactsColumns.CONCRETE_ID + 5516155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.SEARCH_INDEX + 5517155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 5518155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " ON (" + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID 5519155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov + "=" + RawContactsColumns.CONCRETE_CONTACT_ID + ")" + 5520155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " WHERE " + SearchIndexColumns.NAME + " MATCH "); 55212352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, sanitizeMatch(filterParam) + "*"); 5522155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(")"); 55235e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 5525a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 55265e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 5528a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 552946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String accountPromotionSortOrder = getAccountPromotionSortOrder(uri); 553046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(accountPromotionSortOrder)) { 553146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = accountPromotionSortOrder + ", " + EMAIL_FILTER_SORT_ORDER; 55327d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa } else { 55337d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa sortOrder = EMAIL_FILTER_SORT_ORDER; 55347d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa } 5535a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 55365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 55375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55385e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 5539ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 554082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 55417cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 55427cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForStructuredPostal()); 5543ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5544ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5545ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 554648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 554782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 55484da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 55497cf50494501938f175d288077145acf49da8f171Daniel Lehmann qb.appendWhere(" AND " + DataColumns.MIMETYPE_ID + " = " 55507cf50494501938f175d288077145acf49da8f171Daniel Lehmann + mDbHelper.get().getMimeTypeIdForStructuredPostal()); 55514da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 555248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 555348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 555448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 5555d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS: 5556d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS: { 5557763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 55584f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 55594f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 55604f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 5561d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_ID: 5562d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID: { 55635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 5564763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 55654da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 55664da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 55674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 55684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 55694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 5570d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case RAW_CONTACTS_DATA: 5571d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_RAW_CONTACTS_ID_DATA: { 5572d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro int segment = match == RAW_CONTACTS_DATA ? 1 : 2; 5573d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(segment)); 557482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 55754da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 55764da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 557724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 557824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 557924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 55803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case RAW_CONTACTS_ID_STREAM_ITEMS: { 55813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 55823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 55833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 55843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItems.RAW_CONTACT_ID + "=?"); 55853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 55863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 558724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 558882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro case RAW_CONTACTS_ID_STREAM_ITEMS_ID: { 558982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 559082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro long streamItemId = Long.parseLong(uri.getPathSegments().get(3)); 559182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro setTablesAndProjectionMapForStreamItems(qb); 559282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(streamItemId)); 5593c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 559482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro qb.appendWhere(StreamItems.RAW_CONTACT_ID + "=? AND " + 559582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems._ID + "=?"); 559682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro break; 559782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 559882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 559924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID_ENTITIES: { 560024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(2)); 560124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 560224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForRawEntities(qb, uri); 56035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro qb.appendWhere(" AND " + RawContacts._ID + "=?"); 5604e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 5605e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 5606e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 5607d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case DATA: 5608d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_DATA: { 560982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 5610e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 5611e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 5612e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 5613d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case DATA_ID: 5614d9e353f4a13154dace037c99eb1054d85cce2521Dave Santoro case PROFILE_DATA_ID: { 561582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 56164da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 56174da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 5618a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 5619a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 5620a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 5621a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 56224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5623a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 5624a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 5625a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 5626892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sortOrder = " length(lookup.normalized_number) DESC"; 5627a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 5628a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 5629e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 5630e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov String numberE164 = PhoneNumberUtils.formatNumberToE164(number, 56315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getCurrentCountryIso()); 5632892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String normalizedNumber = 5633892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov PhoneNumberUtils.normalizeNumber(number); 56345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().buildPhoneLookupAndContactQuery(qb, normalizedNumber, numberE164); 5635e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 5636e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 5637e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 5638e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 5639a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 5640a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 5641a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 5642ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 5643ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.GROUPS); 5644ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 5645f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 5646ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 5647ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 5648ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5649ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 5650ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.GROUPS); 5651ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 56524da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 56534da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Groups._ID + "=?"); 5654ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 5655ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 5656ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5657ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 5658f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa final boolean returnGroupCountPerAccount = 5659f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa readBooleanQueryParameter(uri, Groups.PARAM_RETURN_GROUP_COUNT_PER_ACCOUNT, 5660f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa false); 5661f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa qb.setTables(Views.GROUPS + " AS " + Tables.GROUPS); 5662f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa qb.setProjectionMap(returnGroupCountPerAccount ? 5663f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa sGroupsSummaryProjectionMapWithGroupCountPerAccount 5664f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa : sGroupsSummaryProjectionMap); 5665f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 5666f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa groupBy = GroupsColumns.CONCRETE_ID; 5667ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 5668ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 5669ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5670b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 56710c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 5672b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 5673b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 5674b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 5675b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 567631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 5677d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 56782d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 56792d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 56802d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 56812d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 568231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 5683d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 5684d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 568531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 568631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 568731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 568831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 56895b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ArrayList<AggregationSuggestionParameter> parameters = null; 56905b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov List<String> query = uri.getQueryParameters("query"); 56915b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov if (query != null && !query.isEmpty()) { 56925b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters = new ArrayList<AggregationSuggestionParameter>(query.size()); 56935b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov for (String parameter : query) { 56945b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov int offset = parameter.indexOf(':'); 56955b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters.add(offset == -1 56965b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ? new AggregationSuggestionParameter( 569776dfa406e2cde19c824983c37fc92c1c5bf63eecDaniel Lehmann AggregationSuggestions.PARAMETER_MATCH_NAME, 56985b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter) 56995b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov : new AggregationSuggestionParameter( 57005b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(0, offset), 57015b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(offset + 1))); 57025b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 57035b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 57045b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 5705763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 57067581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 57075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mAggregator.get().queryAggregationSuggestions(qb, projection, contactId, 57085b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov maxSuggestions, filter, parameters); 570931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 571031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 5711eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 5712eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 5713eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 5714f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 5715e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 5716e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 5717e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 57185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final String groupMembershipMimetypeId = Long.toString(mDbHelper.get() 5719e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 572082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 57215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().isInProjection(projection, Settings.UNGROUPED_COUNT)) { 5722e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 5723e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 572482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 57255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().isInProjection( 57265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro projection, Settings.UNGROUPED_WITH_PHONES)) { 5727e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 5728e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 5729e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 5730eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 5731eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 5732eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 57335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 57345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 57350a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 57365ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 57375ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 57385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 573982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 57400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 57414da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 57424da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=?"); 57435ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 57445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 57455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 5746c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 5747174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery( 57485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get(), uri, projection, limit); 5749c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5750c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 5751c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 57522d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill String lookupKey = uri.getLastPathSegment(); 5753174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String filter = getQueryParameter( 5754174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov uri, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA); 5755174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return mGlobalSearchSupport.handleSearchShortcutRefresh( 57565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get(), projection, lookupKey, filter); 5757c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5758c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 57591b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 5760ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 57611b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 57621b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 57631b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 57641b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 5765ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 57661b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 57671b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 57681b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 57691b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 57701b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 5771ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 57721b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 57731b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 57741b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 57751b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 57761b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 5777ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 57781b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 577971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 57807cf50494501938f175d288077145acf49da8f171Daniel Lehmann String groupMimeTypeId = String.valueOf( 57817cf50494501938f175d288077145acf49da8f171Daniel Lehmann mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 57821b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 57837cf50494501938f175d288077145acf49da8f171Daniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, groupMimeTypeId); 57841b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 57851b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 57863202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro case RAW_CONTACT_ENTITIES: 57873202ae2de5c5fec9f5f61003a0e6b608283e1961Dave Santoro case PROFILE_RAW_CONTACT_ENTITIES: { 5788a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 578946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 579046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 579146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 579246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 579346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 5794a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 57954da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 57964da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 579746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 579846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 579946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 580009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov case PROVIDER_STATUS: { 580109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return queryProviderStatus(uri, projection); 580209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 580309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 5804d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES : { 5805d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 5806d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 5807d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 5808d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 5809d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 5810d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID : { 5811385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov long id = ContentUris.parseId(uri); 5812d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 5813d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 5814385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(id)); 5815d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.appendWhere(Directory._ID + "=?"); 5816d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 5817d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 5818d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 58197a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov case COMPLETE_NAME: { 58207a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return completeName(uri, projection); 58217a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 58227a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 58234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 5824f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 5825c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 58264f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 58274f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 582809e69522745551522c55dff27424496f255def46Daniel Lehmann qb.setStrict(true); 58297f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov 5830ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov Cursor cursor = 58315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro query(mActiveDb.get(), qb, projection, selection, selectionArgs, sortOrder, groupBy, 58325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro limit); 5833ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (readBooleanQueryParameter(uri, ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, false)) { 58345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro cursor = bundleLetterCountExtras(cursor, mActiveDb.get(), qb, selection, 58352ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki selectionArgs, sortOrder, addressBookIndexerCountExpression); 5836ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5837b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (snippetDeferred) { 5838b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson cursor = addDeferredSnippetingExtra(cursor); 5839b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 5840ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return cursor; 58415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 58425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 58435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 58445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 58455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 5846038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 5847038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 5848038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 5849038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 58505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 58515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 58524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 58534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 58544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 58554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 58564f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 58574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 585809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov /** 585909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov * Creates a single-row cursor containing the current status of the provider. 586009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov */ 586109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private Cursor queryProviderStatus(Uri uri, String[] projection) { 586209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 586309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov RowBuilder row = cursor.newRow(); 586409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov for (int i = 0; i < projection.length; i++) { 586509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov if (ProviderStatus.STATUS.equals(projection[i])) { 586609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mProviderStatus); 586709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } else if (ProviderStatus.DATA1.equals(projection[i])) { 586809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mEstimatedStorageRequirement); 586909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 587009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 587109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return cursor; 587209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 587309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 5874a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** 5875a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * Runs the query with the supplied contact ID and lookup ID. If the query succeeds, 5876a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * it returns the resulting cursor, otherwise it returns null and the calling 5877a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * method needs to resolve the lookup key and rerun the query. 5878a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov */ 5879a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private Cursor queryWithContactIdAndLookupKey(SQLiteQueryBuilder lookupQb, 5880a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteDatabase db, Uri uri, 5881a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection, String selection, String[] selectionArgs, 5882a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String sortOrder, String groupBy, String limit, 5883a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn, long contactId, String lookupKeyColumn, String lookupKey) { 5884a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] args; 5885a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (selectionArgs == null) { 5886a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[2]; 5887a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } else { 5888a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[selectionArgs.length + 2]; 5889a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 5890a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5891a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[0] = String.valueOf(contactId); 5892a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[1] = Uri.encode(lookupKey); 5893a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(contactIdColumn + "=? AND " + lookupKeyColumn + "=?"); 5894a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, args, sortOrder, 5895a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov groupBy, limit); 5896a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c.getCount() != 0) { 5897a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 5898a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5899a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5900a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov c.close(); 5901a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return null; 5902a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 590309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 5904bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov private static final class AddressBookIndexQuery { 5905bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String LETTER = "letter"; 5906bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String TITLE = "title"; 5907bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String COUNT = "count"; 5908ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5909bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String[] COLUMNS = new String[] { 5910bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov LETTER, TITLE, COUNT 5911ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 5912ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5913bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_LETTER = 0; 5914bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_TITLE = 1; 5915bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_COUNT = 2; 5916bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 59175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // The first letter of the sort key column is what is used for the index headings. 59185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public static final String SECTION_HEADING = "SUBSTR(%1$s,1,1)"; 591924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 5920de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa public static final String ORDER_BY = LETTER + " COLLATE " + PHONEBOOK_COLLATOR_NAME; 5921ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5922ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5923ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov /** 5924ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * Computes counts by the address book index titles and adds the resulting tally 5925ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * to the returned cursor as a bundle of extras. 5926ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov */ 5927ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov private Cursor bundleLetterCountExtras(Cursor cursor, final SQLiteDatabase db, 59282ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki SQLiteQueryBuilder qb, String selection, String[] selectionArgs, String sortOrder, 59292ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki String countExpression) { 5930409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki if (!(cursor instanceof AbstractCursor)) { 5931409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki Log.w(TAG, "Unable to bundle extras. Cursor is not AbstractCursor."); 5932409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki return cursor; 5933409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki } 5934ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortKey; 5935ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5936ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // The sort order suffix could be something like "DESC". 5937ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // We want to preserve it in the query even though we will change 5938ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // the sort column itself. 5939ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortOrderSuffix = ""; 5940ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (sortOrder != null) { 5941ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int spaceIndex = sortOrder.indexOf(' '); 5942ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (spaceIndex != -1) { 5943ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder.substring(0, spaceIndex); 5944ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortOrderSuffix = sortOrder.substring(spaceIndex); 5945ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 5946ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder; 5947ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5948ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 5949ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = Contacts.SORT_KEY_PRIMARY; 5950ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5951ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5952bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String locale = getLocale().toString(); 5953ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov HashMap<String, String> projectionMap = Maps.newHashMap(); 59545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String sectionHeading = String.format(AddressBookIndexQuery.SECTION_HEADING, sortKey); 5955bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov projectionMap.put(AddressBookIndexQuery.LETTER, 595624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro sectionHeading + " AS " + AddressBookIndexQuery.LETTER); 5957bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 59582ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // If "what to count" is not specified, we just count all records. 59592ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki if (TextUtils.isEmpty(countExpression)) { 59602ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki countExpression = "*"; 59612ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki } 59622ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 5963bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov /** 5964bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * Use the GET_PHONEBOOK_INDEX function, which is an android extension for SQLite3, 5965bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * to map the first letter of the sort key to a character that is traditionally 5966bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * used in phonebooks to represent that letter. For example, in Korean it will 5967bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * be the first consonant in the letter; for Japanese it will be Hiragana rather 5968bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * than Katakana. 5969bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov */ 5970ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.TITLE, 597124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro "GET_PHONEBOOK_INDEX(" + sectionHeading + ",'" + locale + "')" 5972bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov + " AS " + AddressBookIndexQuery.TITLE); 5973ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.COUNT, 59742ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki "COUNT(" + countExpression + ") AS " + AddressBookIndexQuery.COUNT); 5975ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov qb.setProjectionMap(projectionMap); 5976ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5977f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov Cursor indexCursor = qb.query(db, AddressBookIndexQuery.COLUMNS, selection, selectionArgs, 5978ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY, null /* having */, 5979ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY + sortOrderSuffix); 5980ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5981ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov try { 5982f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov int groupCount = indexCursor.getCount(); 5983ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String titles[] = new String[groupCount]; 5984ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int counts[] = new int[groupCount]; 5985bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int indexCount = 0; 5986bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String currentTitle = null; 5987bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 5988bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // Since GET_PHONEBOOK_INDEX is a many-to-1 function, we may end up 5989bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // with multiple entries for the same title. The following code 5990bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // collapses those duplicates. 5991ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov for (int i = 0; i < groupCount; i++) { 5992f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.moveToNext(); 5993bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String title = indexCursor.getString(AddressBookIndexQuery.COLUMN_TITLE); 5994bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int count = indexCursor.getInt(AddressBookIndexQuery.COLUMN_COUNT); 5995bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount == 0 || !TextUtils.equals(title, currentTitle)) { 5996bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles[indexCount] = currentTitle = title; 5997bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount] = count; 5998bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov indexCount++; 5999bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } else { 6000bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount - 1] += count; 6001bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 6002bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 6003bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 6004bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount < groupCount) { 6005bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String[] newTitles = new String[indexCount]; 6006bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(titles, 0, newTitles, 0, indexCount); 6007bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles = newTitles; 6008bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 6009bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int[] newCounts = new int[indexCount]; 6010bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(counts, 0, newCounts, 0, indexCount); 6011bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts = newCounts; 6012ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 6013ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 6014409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki final Bundle bundle = new Bundle(); 6015409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki bundle.putStringArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, titles); 6016409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki bundle.putIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS, counts); 6017409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki 6018409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki ((AbstractCursor) cursor).setExtras(bundle); 6019409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki return cursor; 6020ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } finally { 6021f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.close(); 6022ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 6023ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 6024ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 60252d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill /** 602692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Returns the contact Id for the contact identified by the lookupKey. 602792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Robust against changes in the lookup key: if the key has changed, will 602892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * look up the contact by the raw contact IDs or name encoded in the lookup 602992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * key. 60302d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill */ 60312d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill public long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 60325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 60335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 60345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 603592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov long contactId = -1; 60365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_PROFILE)) { 60375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // We should already be in a profile database context, so just look up a single contact. 60385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro contactId = lookupSingleContactId(db); 60395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 60405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 604192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_SOURCE_ID)) { 604292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdBySourceIds(db, segments); 604392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 604492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 604592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 604692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 604792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 604892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov boolean hasRawContactIds = 604992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID); 605092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds) { 605192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdByRawContactIds(db, segments); 605292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 605392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 605492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 605592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 605692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 605792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds 605892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME)) { 60595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 60605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 60635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private long lookupSingleContactId(SQLiteDatabase db) { 60665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = db.query(Tables.CONTACTS, new String[] {Contacts._ID}, 60675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro null, null, null, null, null, "1"); 60685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro try { 60695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (c.moveToFirst()) { 60705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return c.getLong(0); 60715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 60725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return -1; 60735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 60745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } finally { 60755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro c.close(); 60765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 60775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 60785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 60795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 608043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String TABLE = Views.RAW_CONTACTS; 60815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 60835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 608443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 60855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 60865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 60875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 60885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 609043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int ACCOUNT_TYPE_AND_DATA_SET = 1; 60915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 60925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 60935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 60965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 60975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 60985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 60995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 61005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 610192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID) { 61025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 61035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 61045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 61075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 61085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 61105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 61115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 61125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 611343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String accountTypeAndDataSet = 611443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE_AND_DATA_SET); 61155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 61165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 611743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ContactLookupKey.getAccountHashCode(accountTypeAndDataSet, accountName); 61185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 61195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 61205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 612192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID 612292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 61235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 61245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 61255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 61265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 61305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 61315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 61345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 613692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByRawContactIdQuery { 613743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String TABLE = Views.RAW_CONTACTS; 61385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 61405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 614143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 61425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 614392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts._ID, 61445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 61455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 614743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int ACCOUNT_TYPE_AND_DATA_SET = 1; 61485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 614992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ID = 3; 61505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 615292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByRawContactIds(SQLiteDatabase db, 615392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 615492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 615592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(RawContacts._ID + " IN ("); 61565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 61575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 615892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 615992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(segment.rawContactId); 616092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(","); 61615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 616392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 616492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 61655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 616692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Cursor c = db.query(LookupByRawContactIdQuery.TABLE, LookupByRawContactIdQuery.COLUMNS, 616792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.toString(), null, null, null, null); 616892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov try { 616992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov while (c.moveToNext()) { 617043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String accountTypeAndDataSet = c.getString( 617143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro LookupByRawContactIdQuery.ACCOUNT_TYPE_AND_DATA_SET); 617292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountName = c.getString(LookupByRawContactIdQuery.ACCOUNT_NAME); 617392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int accountHashCode = 617443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ContactLookupKey.getAccountHashCode(accountTypeAndDataSet, accountName); 617592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String rawContactId = c.getString(LookupByRawContactIdQuery.ID); 617692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 617792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 617892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID 617992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 618092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && segment.rawContactId.equals(rawContactId)) { 618192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov segment.contactId = c.getLong(LookupByRawContactIdQuery.CONTACT_ID); 618292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov break; 618392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 618492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 618592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 618692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } finally { 618792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov c.close(); 61885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 619092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return getMostReferencedContactId(segments); 619192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 619292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 619392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByDisplayNameQuery { 619492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 619592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 619692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String COLUMNS[] = { 619792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.CONTACT_ID, 619843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 619992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 620092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 620192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov }; 620292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 620392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int CONTACT_ID = 0; 620443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int ACCOUNT_TYPE_AND_DATA_SET = 1; 620592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_NAME = 2; 620692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int NORMALIZED_NAME = 3; 620792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 620892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 620992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 621092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 62115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 62125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 62135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 62145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 621592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 621692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 62175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 62185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 62195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 62225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 62235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 62245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 62265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 62275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 62285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 622943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String accountTypeAndDataSet = 623043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE_AND_DATA_SET); 62315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 62325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 623343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ContactLookupKey.getAccountHashCode(accountTypeAndDataSet, accountName); 62345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 62355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 62365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 623792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if ((segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 623892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) 623992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 62405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 62415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 62425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 62435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 62475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 62485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 62515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 625392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private boolean lookupKeyContainsType(ArrayList<LookupKeySegment> segments, int lookupType) { 625492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 625592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 625692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == lookupType) { 625792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return true; 625892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 625992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 626092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 626192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return false; 626292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 626392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 6264ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateLookupKeyForRawContact(SQLiteDatabase db, long rawContactId) { 62655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateLookupKeyForRawContact(db, rawContactId); 6266ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov } 6267ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov 62685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 62695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 62705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 62715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 62725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 62735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 62755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 62765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 62785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 62795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 62815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 62825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 62835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 62845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 62855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 62865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 62875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 62885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 62895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 62905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 62925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 62935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 62975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 62985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 62995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 63005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 63015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 63025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 6303763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 6304763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 63054928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, false); 63062f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 63072f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 63082f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa /** 63094928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * @param includeDataUsageStat true when the table should include DataUsageStat table. 63104928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * Note that this uses INNER JOIN instead of LEFT OUTER JOIN, so some of data in Contacts 63114928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * may be dropped. 63122f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa */ 63132f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 63144928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa String[] projection, boolean includeDataUsageStat) { 631582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 6316ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.CONTACTS); 63172f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 63182f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Just for frequently contacted contacts in Strequent Uri handling. 63194928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa if (includeDataUsageStat) { 63202f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa sb.append(" INNER JOIN " + 6321ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann Views.DATA_USAGE_STAT + " AS " + Tables.DATA_USAGE_STAT + 63222f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa " ON (" + 63232f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa DbQueryUtils.concatenateClauses( 63242f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa DataUsageStatColumns.CONCRETE_TIMES_USED + " > 0", 63254928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa RawContacts.CONTACT_ID + "=" + Views.CONTACTS + "." + Contacts._ID) + 63262f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa ")"); 63272f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 63282f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 63297ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts._ID); 63307ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 6331916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 6332916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 6333916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 6334916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 6335916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** 6336916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * Finds name lookup records matching the supplied filter, picks one arbitrary match per 6337916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * contact and joins that with other contacts tables. 6338916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov */ 6339916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void setTablesAndProjectionMapForContactsWithSnippet(SQLiteQueryBuilder qb, Uri uri, 6340b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson String[] projection, String filter, long directoryId, boolean deferredSnippeting) { 63417ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov 63427ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 6343ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.CONTACTS); 6344916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 634503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (filter != null) { 634603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov filter = filter.trim(); 634703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 634803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 634930cc766756461da8d53933f88ea01dd2272a90ebDmitri Plotnikov if (TextUtils.isEmpty(filter) || (directoryId != -1 && directoryId != Directory.DEFAULT)) { 635030cc766756461da8d53933f88ea01dd2272a90ebDmitri Plotnikov sb.append(" JOIN (SELECT NULL AS " + SearchSnippetColumns.SNIPPET + " WHERE 0)"); 63515e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } else { 6352b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson appendSearchIndexJoin(sb, uri, projection, filter, deferredSnippeting); 63535e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 63547ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts._ID); 63557ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 635603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov qb.setTables(sb.toString()); 635703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionWithSnippetMap); 635803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 6359916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 636003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private void appendSearchIndexJoin( 6361b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson StringBuilder sb, Uri uri, String[] projection, String filter, 6362b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson boolean deferredSnippeting) { 6363916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 6364b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (snippetNeeded(projection)) { 636503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String[] args = null; 636603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String snippetArgs = 636703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov getQueryParameter(uri, SearchSnippetColumns.SNIPPET_ARGS_PARAM_KEY); 636803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (snippetArgs != null) { 636903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov args = snippetArgs.split(","); 637003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 637103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 63725e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String startMatch = args != null && args.length > 0 ? args[0] 63735e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_START_MATCH; 63745e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String endMatch = args != null && args.length > 1 ? args[1] 63755e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_END_MATCH; 63765e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String ellipsis = args != null && args.length > 2 ? args[2] 63775e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_ELLIPSIS; 63785e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov int maxTokens = args != null && args.length > 3 ? Integer.parseInt(args[3]) 63795e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_MAX_TOKENS; 63805e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 6381174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov appendSearchIndexJoin( 6382b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson sb, filter, true, startMatch, endMatch, ellipsis, maxTokens, 6383b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson deferredSnippeting); 6384174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } else { 6385b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson appendSearchIndexJoin(sb, filter, false, null, null, null, 0, false); 6386174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 6387174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 6388174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 6389174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov public void appendSearchIndexJoin(StringBuilder sb, String filter, 6390174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean snippetNeeded, String startMatch, String endMatch, String ellipsis, 6391b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson int maxTokens, boolean deferredSnippeting) { 6392174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean isEmailAddress = false; 6393174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String emailAddress = null; 6394174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean isPhoneNumber = false; 6395174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String phoneNumber = null; 6396174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String numberE164 = null; 6397174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 63983716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // If the query consists of a single word, we can do snippetizing after-the-fact for a 63993716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // performance boost. 6400b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson boolean singleTokenSearch = isSingleWordQuery(filter); 64013716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 6402174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov if (filter.indexOf('@') != -1) { 64035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro emailAddress = mDbHelper.get().extractAddressFromEmailAddress(filter); 6404174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov isEmailAddress = !TextUtils.isEmpty(emailAddress); 6405174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } else { 6406174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov isPhoneNumber = isPhoneNumber(filter); 640704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (isPhoneNumber) { 640804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann phoneNumber = PhoneNumberUtils.normalizeNumber(filter); 640904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann numberE164 = PhoneNumberUtils.formatNumberToE164(phoneNumber, 64105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getCountryIso()); 641104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 6412174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 6413174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 6414174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov sb.append(" JOIN (SELECT " + SearchIndexColumns.CONTACT_ID + " AS snippet_contact_id"); 6415174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov if (snippetNeeded) { 64165e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(", "); 64175e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov if (isEmailAddress) { 64183d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append("ifnull("); 64195e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 642004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("||(SELECT MIN(" + Email.ADDRESS + ")"); 642104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" FROM " + Tables.DATA_JOIN_RAW_CONTACTS); 642204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" WHERE " + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 642304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + RawContacts.CONTACT_ID + " AND " + Email.ADDRESS + " LIKE "); 642404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann DatabaseUtils.appendEscapedSQLString(sb, filter + "%"); 642504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(")||"); 64263d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 64273d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append(","); 64283716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 6429b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson // Optimization for single-token search (do only if requested). 6430b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (singleTokenSearch && deferredSnippeting) { 64313716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 64323716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 64333716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 64343716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 64353d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append(")"); 64363d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov } else if (isPhoneNumber) { 64373d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append("ifnull("); 64383d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 643904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("||(SELECT MIN(" + Phone.NUMBER + ")"); 644004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" FROM " + 644104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann Tables.DATA_JOIN_RAW_CONTACTS + " JOIN " + Tables.PHONE_LOOKUP); 644204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" ON " + DataColumns.CONCRETE_ID); 644304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + Tables.PHONE_LOOKUP + "." + PhoneLookupColumns.DATA_ID); 644404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" WHERE " + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 644504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + RawContacts.CONTACT_ID); 644604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" AND " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 644704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(phoneNumber); 644804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("%'"); 644904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (!TextUtils.isEmpty(numberE164)) { 645004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" OR " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 645104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(numberE164); 645204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("%'"); 645304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 645404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(")||"); 64555e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 64565e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 64573716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 6458b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson // Optimization for single-token search (do only if requested). 6459b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (singleTokenSearch && deferredSnippeting) { 64603716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 64613716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 64623716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 64633716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 64645e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(")"); 646503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 646604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann final String normalizedFilter = NameNormalizer.normalize(filter); 646704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (!TextUtils.isEmpty(normalizedFilter)) { 6468b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson // Optimization for single-token search (do only if requested).. 6469b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson if (singleTokenSearch && deferredSnippeting) { 64703716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 64713716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 64723716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("(CASE WHEN EXISTS (SELECT 1 FROM "); 64733716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.RAW_CONTACTS + " AS rc INNER JOIN "); 64743716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.NAME_LOOKUP + " AS nl ON (rc." + RawContacts._ID); 64753716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("=nl." + NameLookupColumns.RAW_CONTACT_ID); 64763716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(") WHERE nl." + NameLookupColumns.NORMALIZED_NAME); 64773716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(" GLOB '" + normalizedFilter + "*' AND "); 64783716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("nl." + NameLookupColumns.NAME_TYPE + "="); 64793716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(NameLookupType.NAME_COLLATION_KEY + " AND "); 64803716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 64813716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("=rc." + RawContacts.CONTACT_ID); 64823716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(") THEN NULL ELSE "); 64833716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 64843716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(" END)"); 64853716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 648604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } else { 648704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("NULL"); 648804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 648903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 64905e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" AS " + SearchSnippetColumns.SNIPPET); 64915e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 649203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 64935e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" FROM " + Tables.SEARCH_INDEX); 64945e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" WHERE "); 64955e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(Tables.SEARCH_INDEX + " MATCH "); 64965e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov if (isEmailAddress) { 64972352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, "\"" + sanitizeMatch(filter) + "*\""); 64983d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov } else if (isPhoneNumber) { 64992352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, 650004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann "\"" + sanitizeMatch(filter) + "*\" OR \"" + phoneNumber + "*\"" 65012352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov + (numberE164 != null ? " OR \"" + numberE164 + "\"" : "")); 650203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 65032352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, sanitizeMatch(filter) + "*"); 65049c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov } 650503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(") ON (" + Contacts._ID + "=snippet_contact_id)"); 6506a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov } 6507a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov 65082352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov private String sanitizeMatch(String filter) { 65092352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov // TODO more robust preprocessing of match expressions 65102352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov return filter.replace('-', ' ').replace('\"', ' '); 65112352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov } 65122352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov 65135e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov private void appendSnippetFunction( 65145e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov StringBuilder sb, String startMatch, String endMatch, String ellipsis, int maxTokens) { 65155e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append("snippet(" + Tables.SEARCH_INDEX + ","); 65165e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 65175e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 65185e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 65195e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 65205e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, ellipsis); 65215e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 65225e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov // The index of the column used for the snippet, "content" 65235e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(",1,"); 65245e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(maxTokens); 65255e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(")"); 65265e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 65275e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 6528763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 6529763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 6530ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.RAW_CONTACTS); 6531763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 6532763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 6533f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 6534763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 6535763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 6536a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForRawEntities(SQLiteQueryBuilder qb, Uri uri) { 6537ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.RAW_ENTITIES); 6538a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sRawEntityProjectionMap); 6539f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 654046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 654146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 654282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 654382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 654446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, distinct, null); 654546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 654646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 654746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 654846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * @param usageType when non-null {@link Tables#DATA_USAGE_STAT} is joined with the specified 654946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * type. 655046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 655146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 655246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String[] projection, boolean distinct, Integer usageType) { 655382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 6554ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.DATA); 655582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 655682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 6557a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, RawContacts.CONTACT_ID); 6558a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 6559a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 6560a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 65613296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 656246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (usageType != null) { 656346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa appendDataUsageStatJoin(sb, usageType, DataColumns.CONCRETE_ID); 656446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 656546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 656682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 6567f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov 6568f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov boolean useDistinct = distinct 65695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro || !mDbHelper.get().isInProjection(projection, DISTINCT_DATA_PROHIBITING_COLUMNS); 6570f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov qb.setDistinct(useDistinct); 6571f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov qb.setProjectionMap(useDistinct ? sDistinctDataProjectionMap : sDataProjectionMap); 6572f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 6573ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 6574ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 65750a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 65760a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 65770a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 6578ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.DATA); 65790a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 6580a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 6581a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 65820a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 6583a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 6584a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 6585a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6586a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 65873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void setTablesAndProjectionMapForStreamItems(SQLiteQueryBuilder qb) { 65889b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann qb.setTables(Views.STREAM_ITEMS); 65893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.setProjectionMap(sStreamItemsProjectionMap); 65903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 65913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 65923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void setTablesAndProjectionMapForStreamItemPhotos(SQLiteQueryBuilder qb) { 65931dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro qb.setTables(Tables.PHOTO_FILES 65941dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + " JOIN " + Tables.STREAM_ITEM_PHOTOS + " ON (" 65951dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + StreamItemPhotosColumns.CONCRETE_PHOTO_FILE_ID + "=" 65961dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + PhotoFilesColumns.CONCRETE_ID 65971dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + ") JOIN " + Tables.STREAM_ITEMS + " ON (" 65981dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=" 65990bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + StreamItemsColumns.CONCRETE_ID + ")" 66000bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + " JOIN " + Tables.RAW_CONTACTS + " ON (" 66010bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + StreamItemsColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID 66020bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + ")"); 66033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.setProjectionMap(sStreamItemPhotosProjectionMap); 66043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 66053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 6606a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForEntities(SQLiteQueryBuilder qb, Uri uri, 6607a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection) { 6608a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 6609ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.ENTITIES); 6610a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" data"); 6611a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6612a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts.Entity.CONTACT_ID); 6613a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 6614a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, Contacts.Entity.DATA_ID); 6615a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, Contacts.Entity.DATA_ID); 6616a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6617a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 6618a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sEntityProjectionMap); 6619f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro appendAccountFromParameter(qb, uri); 6620a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6621a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6622a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactStatusUpdateJoin(StringBuilder sb, String[] projection, 6623a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lastStatusUpdateIdColumn) { 66245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, 6625a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS, 6626a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 6627a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 6628a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 6629a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 6630a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 6631a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.ALIAS + 6632a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + lastStatusUpdateIdColumn + "=" 6633a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 66340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 6635a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 66360a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 6637a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataStatusUpdateJoin(StringBuilder sb, String[] projection, 6638a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 66395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, 66400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 66410a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 66420a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 66430a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 66440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 66450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 6646a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 6647a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + dataIdColumn + ")"); 66480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 6649a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6650a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 665146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private void appendDataUsageStatJoin(StringBuilder sb, int usageType, String dataIdColumn) { 665246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" LEFT OUTER JOIN " + Tables.DATA_USAGE_STAT + 665346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa " ON (" + DataUsageStatColumns.CONCRETE_DATA_ID + "=" + dataIdColumn + 665446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa " AND " + DataUsageStatColumns.CONCRETE_USAGE_TYPE + "=" + usageType + ")"); 665546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 665646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 6657a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactPresenceJoin(StringBuilder sb, String[] projection, 6658a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn) { 66595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, 6660a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_PRESENCE, Contacts.CONTACT_CHAT_CAPABILITY)) { 6661a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 6662a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + contactIdColumn + " = " 6663a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + ")"); 6664a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6665a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6666a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6667a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataPresenceJoin(StringBuilder sb, String[] projection, 6668a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 66695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, Data.PRESENCE, Data.CHAT_CAPABILITY)) { 6670a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 6671a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdates.DATA_ID + "=" + dataIdColumn + ")"); 6672a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6673a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6674a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 667524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private boolean appendLocalDirectorySelectionIfNeeded(SQLiteQueryBuilder qb, long directoryId) { 6676385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov if (directoryId == Directory.DEFAULT) { 6677385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov qb.appendWhere(Contacts._ID + " IN " + Tables.DEFAULT_DIRECTORY); 667824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return true; 6679385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } else if (directoryId == Directory.LOCAL_INVISIBLE){ 6680385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov qb.appendWhere(Contacts._ID + " NOT IN " + Tables.DEFAULT_DIRECTORY); 668124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return true; 668224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 668324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return false; 668424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 668524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 6686f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 6687f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 6688f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 668943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro final String dataSet = getQueryParameter(uri, RawContacts.DATA_SET); 6690e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6691e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 6692e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 6693e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 66945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 6695fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 6696e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 6697e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6698e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 6699e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 6700e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 6701e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 670243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String toAppend = RawContacts.ACCOUNT_NAME + "=" 67034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 67044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 670543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + DatabaseUtils.sqlEscapeString(accountType); 6706f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (dataSet == null) { 6707f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro toAppend += " AND " + RawContacts.DATA_SET + " IS NULL"; 6708f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } else { 6709f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro toAppend += " AND " + RawContacts.DATA_SET + "=" + 6710f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro DatabaseUtils.sqlEscapeString(dataSet); 671143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 671243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro qb.appendWhere(toAppend); 67134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 67144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 67154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 67164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 67174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 6718e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 6719f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 6720f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 672143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro final String dataSet = getQueryParameter(uri, RawContacts.DATA_SET); 6722e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6723e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 6724e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 6725e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 67265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 6727fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 6728e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 6729e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6730e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 6731e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 6732e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 6733e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 6734e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 6735e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 6736e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 6737e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 6738f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro if (dataSet == null) { 6739f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro selectionSb.append(" AND " + RawContacts.DATA_SET + " IS NULL"); 6740f9b77edaf5855bf6932fbc4b4b4342273669efefDave Santoro } else { 674143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro selectionSb.append(" AND " + RawContacts.DATA_SET + "=") 674243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .append(DatabaseUtils.sqlEscapeString(dataSet)); 674343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 6744e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 6745e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 6746e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 6747e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 6748e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 6749e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 6750e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 6751e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 6752e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 6753e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 6754e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 67557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 6756c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 6757c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 6758c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 6759c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 6760c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 6761f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String getLimit(Uri uri) { 67622e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov String limitParam = getQueryParameter(uri, ContactsContract.LIMIT_PARAM_KEY); 6763c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 6764c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 6765c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6766c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 6767c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 6768c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 6769c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 6770c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 6771c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 6772c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6773c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 6774c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 6775c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 6776c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 6777c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6778c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6779c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 6780b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 6781f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 6782f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (mode.equals("r")) { 6783f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro waitForAccess(mReadAccessLatch); 6784f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 6785f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro waitForAccess(mWriteAccessLatch); 6786f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 67875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 67885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 67895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileProvider.openAssetFile(uri, mode); 67905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 67915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 67925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mode.equals("r")) { 67935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDb = mDbHelper.get().getReadableDatabase(); 67945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 67955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDb = mDbHelper.get().getWritableDatabase(); 67965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 67975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return openAssetFileLocal(uri, mode); 67985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 67995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 68005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 68015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public AssetFileDescriptor openAssetFileLocal(Uri uri, String mode) 68025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throws FileNotFoundException { 68035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 68045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 68055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 68065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 68075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 6808415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 6809b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 6810b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 6811a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 6812bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro long contactId = Long.parseLong(uri.getPathSegments().get(1)); 68135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return openPhotoAssetFile(mActiveDb.get(), uri, mode, 681424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Data._ID + "=" + Contacts.PHOTO_ID + " AND " + 681524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro RawContacts.CONTACT_ID + "=?", 6816bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro new String[]{String.valueOf(contactId)}); 6817e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 6818b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 6819f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_ID_DISPLAY_PHOTO: { 6820f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (!mode.equals("r")) { 6821f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new IllegalArgumentException( 6822f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Display photos retrieved by contact ID can only be read."); 6823f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6824f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long contactId = Long.parseLong(uri.getPathSegments().get(1)); 68255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.CONTACTS, 6826f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro new String[]{Contacts.PHOTO_FILE_ID}, 6827f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Contacts._ID + "=?", new String[]{String.valueOf(contactId)}, 6828f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro null, null, null); 6829f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6830f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 6831f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = c.getLong(0); 6832f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 6833f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 6834f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 6835f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6836f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6837f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6838bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_PHOTO: 6839bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_ID_PHOTO: 6840f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_DISPLAY_PHOTO: 6841f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_ID_DISPLAY_PHOTO: { 6842f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (!mode.equals("r")) { 6843f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new IllegalArgumentException( 6844bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro "Photos retrieved by contact lookup key can only be read."); 6845f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6846f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro List<String> pathSegments = uri.getPathSegments(); 6847f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro int segmentCount = pathSegments.size(); 6848f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (segmentCount < 4) { 68495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 6850f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Missing a lookup key", uri)); 6851f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6852bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro 6853bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro boolean forDisplayPhoto = (match == CONTACTS_LOOKUP_ID_DISPLAY_PHOTO 6854bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro || match == CONTACTS_LOOKUP_DISPLAY_PHOTO); 6855f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String lookupKey = pathSegments.get(2); 6856bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro String[] projection = new String[]{Contacts.PHOTO_ID, Contacts.PHOTO_FILE_ID}; 6857f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (segmentCount == 5) { 6858f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long contactId = Long.parseLong(pathSegments.get(3)); 6859f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 6860f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 68615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 6862f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro projection, null, null, null, null, null, 6863f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey); 6864f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (c != null) { 6865f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6866f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 6867bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro if (forDisplayPhoto) { 6868bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro long photoFileId = 6869bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro c.getLong(c.getColumnIndex(Contacts.PHOTO_FILE_ID)); 6870bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro return openDisplayPhotoForRead(photoFileId); 6871bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } else { 6872bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro long photoId = c.getLong(c.getColumnIndex(Contacts.PHOTO_ID)); 6873bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro return openPhotoAssetFile(mActiveDb.get(), uri, mode, 6874bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro Data._ID + "=?", new String[]{String.valueOf(photoId)}); 6875bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } 6876f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 6877f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 6878f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6879f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6880f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6881f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6882f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 6883f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro setTablesAndProjectionMapForContacts(qb, uri, projection); 68845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 68855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), projection, Contacts._ID + "=?", 6886f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro new String[]{String.valueOf(contactId)}, null, null, null); 6887f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6888f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 6889bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro if (forDisplayPhoto) { 6890bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro long photoFileId = c.getLong(c.getColumnIndex(Contacts.PHOTO_FILE_ID)); 6891bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro return openDisplayPhotoForRead(photoFileId); 6892bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } else { 6893bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro long photoId = c.getLong(c.getColumnIndex(Contacts.PHOTO_ID)); 6894bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro return openPhotoAssetFile(mActiveDb.get(), uri, mode, 6895bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro Data._ID + "=?", new String[]{String.valueOf(photoId)}); 6896bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro } 6897f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 6898f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 6899f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6900f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6901f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6902f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case RAW_CONTACTS_ID_DISPLAY_PHOTO: { 6903f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 6904f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro boolean writeable = !mode.equals("r"); 6905f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6906f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Find the primary photo data record for this raw contact. 6907f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 6908f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String[] projection = new String[]{Data._ID, Photo.PHOTO_FILE_ID}; 6909f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro setTablesAndProjectionMapForData(qb, uri, projection, false); 69107cf50494501938f175d288077145acf49da8f171Daniel Lehmann long photoMimetypeId = mDbHelper.get().getMimeTypeId(Photo.CONTENT_ITEM_TYPE); 69115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), projection, 69127cf50494501938f175d288077145acf49da8f171Daniel Lehmann Data.RAW_CONTACT_ID + "=? AND " + DataColumns.MIMETYPE_ID + "=?", 69137cf50494501938f175d288077145acf49da8f171Daniel Lehmann new String[]{String.valueOf(rawContactId), String.valueOf(photoMimetypeId)}, 6914f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro null, null, Data.IS_PRIMARY + " DESC"); 6915f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long dataId = 0; 6916f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = 0; 6917f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6918f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (c.getCount() >= 1) { 6919f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 6920f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro dataId = c.getLong(0); 6921f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro photoFileId = c.getLong(1); 6922f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6923f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 6924f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 6925f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6926f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6927f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // If writeable, open a writeable file descriptor that we can monitor. 6928f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // When the caller finishes writing content, we'll process the photo and 6929f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // update the data record. 6930f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (writeable) { 6931f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForWrite(rawContactId, dataId, uri, mode); 6932f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 6933f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 6934f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6935f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6936f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6937f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case DISPLAY_PHOTO: { 6938f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = ContentUris.parseId(uri); 6939f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (!mode.equals("r")) { 6940f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new IllegalArgumentException( 6941f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Display photos retrieved by key can only be read."); 6942f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6943f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 6944f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6945f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6946e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov case DATA_ID: { 694724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long dataId = Long.parseLong(uri.getPathSegments().get(1)); 69487cf50494501938f175d288077145acf49da8f171Daniel Lehmann long photoMimetypeId = mDbHelper.get().getMimeTypeId(Photo.CONTENT_ITEM_TYPE); 69495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return openPhotoAssetFile(mActiveDb.get(), uri, mode, 69507cf50494501938f175d288077145acf49da8f171Daniel Lehmann Data._ID + "=? AND " + DataColumns.MIMETYPE_ID + "=" + photoMimetypeId, 695124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro new String[]{String.valueOf(dataId)}); 6952d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 6953d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 6954fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen case PROFILE_AS_VCARD: { 6955fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // When opening a contact as file, we pass back contents as a 6956fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // vCard-encoded stream. We build into a local buffer first, 6957fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // then pipe into MemoryFile once the exact size is known. 6958fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 6959fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(uri, localStream, null, null); 6960fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen return buildAssetFileDescriptor(localStream); 6961fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen } 696242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 6963fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen case CONTACTS_AS_VCARD: { 696442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // When opening a contact as file, we pass back contents as a 696542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // vCard-encoded stream. We build into a local buffer first, 696642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // then pipe into MemoryFile once the exact size is known. 696742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 6968fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(uri, localStream, null, null); 6969f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return buildAssetFileDescriptor(localStream); 697042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 697142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 697242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 697342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKeys = uri.getPathSegments().get(2); 697442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String[] loopupKeyList = lookupKeys.split(":"); 697542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final StringBuilder inBuilder = new StringBuilder(); 6976fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen Uri queryUri = Contacts.CONTENT_URI; 697742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann int index = 0; 6978fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen 6979d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // SQLite has limits on how many parameters can be used 6980d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // so the IDs are concatenated to a query string here instead 698142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann for (String lookupKey : loopupKeyList) { 698242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann if (index == 0) { 6983d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append("("); 698442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } else { 6985d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append(","); 698642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 69875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // TODO: Figure out what to do if the profile contact is in the list. 69885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 698924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro inBuilder.append(contactId); 699042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann index++; 699142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 699242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann inBuilder.append(')'); 699342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + " IN " + inBuilder.toString(); 6994d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 6995d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 6996d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 6997d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 6998d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 6999fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(queryUri, localStream, selection, null); 7000f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return buildAssetFileDescriptor(localStream); 7001d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7002b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 7003b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 70045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new FileNotFoundException(mDbHelper.get().exceptionMessage( 70055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro "File does not exist", uri)); 7006b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 7007b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 7008b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 7009afc8e7ad6e5208db6c87b8500ecc1246ad966d62Dave Santoro private AssetFileDescriptor openPhotoAssetFile(SQLiteDatabase db, Uri uri, String mode, 7010afc8e7ad6e5208db6c87b8500ecc1246ad966d62Dave Santoro String selection, String[] selectionArgs) 7011e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throws FileNotFoundException { 7012e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov if (!"r".equals(mode)) { 70135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new FileNotFoundException(mDbHelper.get().exceptionMessage("Mode " + mode 7014e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov + " not supported.", uri)); 7015e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 7016e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 7017e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String sql = 7018ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann "SELECT " + Photo.PHOTO + " FROM " + Views.DATA + 7019e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov " WHERE " + selection; 702008ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood try { 7021f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor( 7022f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert DatabaseUtils.blobFileDescriptorForQuery(db, sql, selectionArgs)); 702308ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } catch (SQLiteDoneException e) { 702408ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood // this will happen if the DB query returns no rows (i.e. contact does not exist) 702508ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood throw new FileNotFoundException(uri.toString()); 702608ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } 7027e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 7028e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 7029f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 7030f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Opens a display photo from the photo store for reading. 7031f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param photoFileId The display photo file ID 7032f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @return An asset file descriptor that allows the file to be read. 7033f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @throws FileNotFoundException If no photo file for the given ID exists. 7034f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 7035f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private AssetFileDescriptor openDisplayPhotoForRead(long photoFileId) 7036f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throws FileNotFoundException { 70375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PhotoStore.Entry entry = mPhotoStore.get().get(photoFileId); 7038f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (entry != null) { 7039f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return makeAssetFileDescriptor( 7040f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ParcelFileDescriptor.open(new File(entry.path), 7041f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ParcelFileDescriptor.MODE_READ_ONLY), 7042f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro entry.size); 7043f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 7044f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS); 7045f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new FileNotFoundException("No photo file found for ID " + photoFileId); 7046f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7047f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7048f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7049f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 7050f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Opens a file descriptor for a photo to be written. When the caller completes writing 7051f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * to the file (closing the output stream), the image will be parsed out and processed. 7052f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * If processing succeeds, the given raw contact ID's primary photo record will be 7053f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * populated with the inserted image (if no primary photo record exists, the data ID can 7054f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * be left as 0, and a new data record will be inserted). 7055f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param rawContactId Raw contact ID this photo entry should be associated with. 7056f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param dataId Data ID for a photo mimetype that will be updated with the inserted 7057f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * image. May be set to 0, in which case the inserted image will trigger creation 7058f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * of a new primary photo image data row for the raw contact. 7059f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param uri The URI being used to access this file. 7060f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param mode Read/write mode string. 7061f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @return An asset file descriptor the caller can use to write an image file for the 7062f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * raw contact. 7063f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 7064f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private AssetFileDescriptor openDisplayPhotoForWrite(long rawContactId, long dataId, Uri uri, 7065f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String mode) { 7066f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 7067c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro ParcelFileDescriptor[] pipeFds = ParcelFileDescriptor.createPipe(); 7068c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro PipeMonitor pipeMonitor = new PipeMonitor(rawContactId, dataId, pipeFds[0]); 7069c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro pipeMonitor.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[]) null); 7070c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro return new AssetFileDescriptor(pipeFds[1], 0, AssetFileDescriptor.UNKNOWN_LENGTH); 7071f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } catch (IOException ioe) { 7072f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Log.e(TAG, "Could not create temp image file in mode " + mode); 7073f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return null; 7074f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7075f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7076f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7077f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 7078c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro * Async task that monitors the given file descriptor (the read end of a pipe) for 7079c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro * the writer finishing. If the data from the pipe contains a valid image, the image 7080c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro * is either inserted into the given raw contact or updated in the given data row. 7081f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 7082c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro private class PipeMonitor extends AsyncTask<Object, Object, Object> { 7083c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro private final ParcelFileDescriptor mDescriptor; 7084f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private final long mRawContactId; 7085f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private final long mDataId; 7086c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro private PipeMonitor(long rawContactId, long dataId, ParcelFileDescriptor descriptor) { 7087f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mRawContactId = rawContactId; 7088f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mDataId = dataId; 7089c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro mDescriptor = descriptor; 7090f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7091f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7092f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro @Override 7093c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro protected Object doInBackground(Object... params) { 7094c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro AutoCloseInputStream is = new AutoCloseInputStream(mDescriptor); 7095f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 7096c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro Bitmap b = BitmapFactory.decodeStream(is); 7097f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (b != null) { 7098fa4db3db4146a26f154ef2e89352ad70a5415b8eDaniel Lehmann waitForAccess(mWriteAccessLatch); 7099f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro PhotoProcessor processor = new PhotoProcessor(b, mMaxDisplayPhotoDim, 7100f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mMaxThumbnailPhotoDim); 7101f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7102f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Store the compressed photo in the photo store. 71035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PhotoStore photoStore = ContactsContract.isProfileId(mRawContactId) 71045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ? mProfilePhotoStore 71055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro : mContactsPhotoStore; 71065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long photoFileId = photoStore.insert(processor); 7107f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7108c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro // Depending on whether we already had a data row to attach the photo 7109c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro // to, do an update or insert. 7110f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (mDataId != 0) { 7111f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Update the data record with the new photo. 7112f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ContentValues updateValues = new ContentValues(); 7113f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7114f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Signal that photo processing has already been handled. 7115f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.put(DataRowHandlerForPhoto.SKIP_PROCESSING_KEY, true); 7116f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7117f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (photoFileId != 0) { 7118f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.put(Photo.PHOTO_FILE_ID, photoFileId); 7119f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7120f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.put(Photo.PHOTO, processor.getThumbnailPhotoBytes()); 7121c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro update(ContentUris.withAppendedId(Data.CONTENT_URI, mDataId), 7122c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro updateValues, null, null); 7123f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 7124f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Insert a new primary data record with the photo. 7125f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ContentValues insertValues = new ContentValues(); 7126f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7127f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Signal that photo processing has already been handled. 7128f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(DataRowHandlerForPhoto.SKIP_PROCESSING_KEY, true); 7129f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7130f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 7131f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Data.IS_PRIMARY, 1); 7132f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (photoFileId != 0) { 7133f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Photo.PHOTO_FILE_ID, photoFileId); 7134f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7135f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Photo.PHOTO, processor.getThumbnailPhotoBytes()); 7136f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insert(RawContacts.CONTENT_URI.buildUpon() 7137f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .appendPath(String.valueOf(mRawContactId)) 7138f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .appendPath(RawContacts.Data.CONTENT_DIRECTORY).build(), 7139f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues); 7140f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7141c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro 7142f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7143c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro } catch (IOException e) { 7144c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro throw new RuntimeException(e); 7145f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7146c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro return null; 7147f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7148f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7149f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7150d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 7151d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7152d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 7153f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert * Returns an {@link AssetFileDescriptor} backed by the 7154d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 7155d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 7156f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 7157d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 7158d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 7159d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7160d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 7161d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7162f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor( 7163f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert ParcelFileDescriptor.fromData(byteData, CONTACT_MEMORY_FILE_NAME), 7164f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert byteData.length); 7165d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 7166ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert Log.w(TAG, "Problem writing stream into an ParcelFileDescriptor: " + e.toString()); 7167ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert return null; 7168d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7169d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7170d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7171f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor makeAssetFileDescriptor(ParcelFileDescriptor fd) { 7172f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor(fd, AssetFileDescriptor.UNKNOWN_LENGTH); 7173f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 7174f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 7175f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor makeAssetFileDescriptor(ParcelFileDescriptor fd, long length) { 7176f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return fd != null ? new AssetFileDescriptor(fd, 0, length) : null; 7177f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 7178f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 7179d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 7180d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 7181d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 7182d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 7183d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 7184fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen private void outputRawContactsAsVCard(Uri uri, OutputStream stream, 7185fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen String selection, String[] selectionArgs) { 7186d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 7187dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen int vcardconfig = VCardConfig.VCARD_TYPE_DEFAULT; 7188fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen if(uri.getBooleanQueryParameter( 7189fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen Contacts.QUERY_PARAMETER_VCARD_NO_PHOTO, false)) { 7190dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen vcardconfig |= VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT; 7191dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen } 71927a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa final VCardComposer composer = 7193dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen new VCardComposer(context, vcardconfig, false); 7194108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Writer writer = null; 7195108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa try { 7196108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer = new BufferedWriter(new OutputStreamWriter(stream)); 7197fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen if (!composer.init(uri, selection, selectionArgs, null)) { 7198108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.w(TAG, "Failed to init VCardComposer"); 7199108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return; 7200108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 7201d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7202108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa while (!composer.isAfterLast()) { 7203108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer.write(composer.createOneEntry()); 7204108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 7205108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } catch (IOException e) { 7206108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.e(TAG, "IOException: " + e); 7207108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } finally { 7208108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa composer.terminate(); 7209108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa if (writer != null) { 7210108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa try { 7211108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer.close(); 7212108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } catch (IOException e) { 7213108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.w(TAG, "IOException during closing output stream: " + e); 7214108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 7215d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7216d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7217d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7218b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 72194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 72204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 7221415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 7222415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov waitForAccess(mReadAccessLatch); 7223415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 7224a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 72254f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 7226b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 7227be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 72282d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill case CONTACTS_LOOKUP: 7229b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 7230b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 723124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: 7232b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 7233f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 723442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: 723524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: 7236f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 7237f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov case CONTACTS_ID_PHOTO: 7238bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_PHOTO: 7239bd20dbedba706fdf2db7acb1c7d4391e57129d44Dave Santoro case CONTACTS_LOOKUP_ID_PHOTO: 7240f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_ID_DISPLAY_PHOTO: 7241f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_DISPLAY_PHOTO: 7242f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_ID_DISPLAY_PHOTO: 7243f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case RAW_CONTACTS_ID_DISPLAY_PHOTO: 7244f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case DISPLAY_PHOTO: 7245f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return "image/jpeg"; 7246b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 724724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS: 7248be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 7249b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 725024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID: 7251b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 7252f481f22a9323fe338672f99b88b26c5f0725cd42David Brown case DATA: 725324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_DATA: 7254f481f22a9323fe338672f99b88b26c5f0725cd42David Brown return Data.CONTENT_TYPE; 7255508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 72565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long id = ContentUris.parseId(uri); 72575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (ContactsContract.isProfileId(id)) { 72585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileHelper.getDataMimeType(id); 72595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 72605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mContactsHelper.getDataMimeType(id); 72615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 726248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 726348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 726448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 726548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 72669005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov case PHONE_LOOKUP: 72679005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov return PhoneLookup.CONTENT_TYPE; 726848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 726948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 727048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 727148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 727248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 727348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 727448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 727548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 7276b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 7277b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 7278b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 7279b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 7280b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 7281b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 7282b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 7283b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 7284c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 7285c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 7286c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 7287c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 7288d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES: 7289d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_TYPE; 7290d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID: 7291d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_ITEM_TYPE; 7292af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS: 7293af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.CONTENT_TYPE; 7294af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_ID: 7295af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.CONTENT_ITEM_TYPE; 7296af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_ID_PHOTOS: 7297af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.StreamItemPhotos.CONTENT_TYPE; 7298af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_ID_PHOTOS_ID: 7299af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.StreamItemPhotos.CONTENT_ITEM_TYPE; 7300af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_PHOTOS: 7301af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki throw new UnsupportedOperationException("Not supported for write-only URI " + uri); 730261efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 730361efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 73044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 73054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 73067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 730709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov public String[] getDefaultProjection(Uri uri) { 730809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov final int match = sUriMatcher.match(uri); 730909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov switch (match) { 731009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS: 731109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP: 731209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_ID: 731309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP_ID: 731409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 731524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: 731609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsProjectionMap.getColumnNames(); 731709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 73188727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov case CONTACTS_ID_ENTITIES: 731924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_ENTITIES: 73208727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov return sEntityProjectionMap.getColumnNames(); 73218727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov 732209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_VCARD: 732309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_MULTI_VCARD: 732424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: 732509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsVCardProjectionMap.getColumnNames(); 732609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 732709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS: 732809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS_ID: 732924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS: 733024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID: 733109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sRawContactsProjectionMap.getColumnNames(); 733209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 733309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DATA_ID: 733409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES: 733509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES_ID: 733609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS: 733709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS_ID: 733809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS: 733909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS_ID: 734024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_DATA: 734109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDataProjectionMap.getColumnNames(); 734209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 734309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONE_LOOKUP: 734409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sPhoneLookupProjectionMap.getColumnNames(); 734509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 734609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 734709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 734809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sAggregationExceptionsProjectionMap.getColumnNames(); 734909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 735009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case SETTINGS: 735109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sSettingsProjectionMap.getColumnNames(); 735209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 735309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES: 735409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES_ID: 735509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDirectoryProjectionMap.getColumnNames(); 735609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 735709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov default: 735809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return null; 735909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 736009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 736109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 7362f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 7363f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 7364f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 7365f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 7366f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7367f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 7368f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 7369f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 7370f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 73715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().insertNameLookup(rawContactId, dataId, lookupType, name); 7372f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7373f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 7374f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 7375f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 7376d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov return mCommonNicknameCache.getCommonNicknameClusters(normalizedName); 7377f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7378f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7379f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 73802d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 7381d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 7382d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 7383d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 7384d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 7385d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 7386d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 7387d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 7388e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 7389916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 7390916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + "))"); 7391e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 7392e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 73939a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov public boolean isPhoneNumber(String filter) { 73949a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov boolean atLeastOneDigit = false; 73959a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov int len = filter.length(); 73969a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov for (int i = 0; i < len; i++) { 73979a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov char c = filter.charAt(i); 73989a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (c >= '0' && c <= '9') { 73999a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov atLeastOneDigit = true; 74009a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } else if (c != '*' && c != '#' && c != '+' && c != 'N' && c != '.' && c != ';' 74019a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov && c != '-' && c != '(' && c != ')' && c != ' ') { 74029a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return false; 74039a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 74049a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 74059a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return atLeastOneDigit; 74069a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 74079a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 74084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 74097a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * Takes components of a name from the query parameters and returns a cursor with those 74107a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * components as well as all missing components. There is no database activity involved 74117a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * in this so the call can be made on the UI thread. 74127a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov */ 74137a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private Cursor completeName(Uri uri, String[] projection) { 74147a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (projection == null) { 74157a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov projection = sDataProjectionMap.getColumnNames(); 74167a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74177a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74187a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ContentValues values = new ContentValues(); 7419f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov DataRowHandlerForStructuredName handler = (DataRowHandlerForStructuredName) 7420f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov getDataRowHandler(StructuredName.CONTENT_ITEM_TYPE); 74217a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74227a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov copyQueryParamsToContentValues(values, uri, 74237a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.DISPLAY_NAME, 74247a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PREFIX, 74257a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.GIVEN_NAME, 74267a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.MIDDLE_NAME, 74277a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.FAMILY_NAME, 74287a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.SUFFIX, 74297a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_NAME, 74307a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_FAMILY_NAME, 74317a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_MIDDLE_NAME, 74327a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_GIVEN_NAME 74337a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ); 74347a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74357a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov handler.fixStructuredNameComponents(values, values); 74367a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74377a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 74387a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov Object[] row = new Object[projection.length]; 74397a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (int i = 0; i < projection.length; i++) { 74407a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov row[i] = values.get(projection[i]); 74417a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74427a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov cursor.addRow(row); 74437a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return cursor; 74447a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74457a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74467a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private void copyQueryParamsToContentValues(ContentValues values, Uri uri, String... columns) { 74477a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (String column : columns) { 74487a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov String param = uri.getQueryParameter(column); 74497a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (param != null) { 74507a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov values.put(column, param); 74517a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74527a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74537a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 74547a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74557a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 74567a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov /** 74574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 74584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 74594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 7460b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 7461b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 7462b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 7463b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 7464b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 74654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 74664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 7467b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 7468b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 7469b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 7470caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 74715e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 74725e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 74735e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 74745e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 74755e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 74765e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 74775e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 74785e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 74795e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 74805e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 74815e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 7482caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 7483caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 7484caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 74855f1f4a062ac34d75d2dbf586702cbeb121cf09caDmitri Plotnikov Account[] accounts = accountManager.getAccountsByType(DEFAULT_ACCOUNT_TYPE); 7486caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 7487caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 7488caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 7489caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 74906f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 7491caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 74926f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 7493caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 7494f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 749573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov /** 749643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * Returns true if the specified account type and data set is writable. 749773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov */ 749843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro protected boolean isWritableAccountWithDataSet(String accountTypeAndDataSet) { 749943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (accountTypeAndDataSet == null) { 7500bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov return true; 7501bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov } 7502bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov 750343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Boolean writable = mAccountWritability.get(accountTypeAndDataSet); 750473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable != null) { 750573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 750673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 750773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 7508627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov IContentService contentService = ContentResolver.getContentService(); 7509627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 751043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // TODO(dsantoro): Need to update this logic to allow for sub-accounts. 7511627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 7512627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (ContactsContract.AUTHORITY.equals(sync.authority) && 751343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountTypeAndDataSet.equals(sync.accountType)) { 751473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = sync.supportsUploading(); 751573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov break; 7516627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 7517627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 7518627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } catch (RemoteException e) { 7519627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 7520627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 752173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 752273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable == null) { 752373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = false; 752473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 752573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 752643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro mAccountWritability.put(accountTypeAndDataSet, writable); 752773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 7528627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 7529b4e61e064b59e8076df81b061add9fb358fd2ed9Dmitri Plotnikov 7530d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 7531f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static boolean readBooleanQueryParameter(Uri uri, String parameter, 7532f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean defaultValue) { 7533f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7534f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // Manually parse the query, which is much faster than calling uri.getQueryParameter 7535f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 7536f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 7537f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 7538f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7539f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7540f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = query.indexOf(parameter); 7541f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 7542f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 7543f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7544f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7545f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameter.length(); 7546f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7547f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return !matchQueryParameter(query, index, "=0", false) 7548f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && !matchQueryParameter(query, index, "=false", true); 7549f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7550f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7551f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private static boolean matchQueryParameter(String query, int index, String value, 7552f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean ignoreCase) { 7553f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int length = value.length(); 7554f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return query.regionMatches(ignoreCase, index, value, 0, length) 7555f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && (query.length() == index + length || query.charAt(index + length) == '&'); 7556f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7557f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7558f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /** 7559f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * A fast re-implementation of {@link Uri#getQueryParameter} 7560f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov */ 7561f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static String getQueryParameter(Uri uri, String parameter) { 7562f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 7563f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 7564f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 7565f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7566f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7567f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int queryLength = query.length(); 7568f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int parameterLength = parameter.length(); 7569f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7570f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String value; 7571f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = 0; 7572f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov while (true) { 7573f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index = query.indexOf(parameter, index); 7574f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 7575f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 75765fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa } 75775fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa 75785fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // Should match against the whole parameter instead of its suffix. 75795fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // e.g. The parameter "param" must not be found in "some_param=val". 75805fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa if (index > 0) { 75815fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa char prevChar = query.charAt(index - 1); 75825fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa if (prevChar != '?' && prevChar != '&') { 75835fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // With "some_param=val1¶m=val2", we should find second "param" occurrence. 75845fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa index += parameterLength; 75855fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa continue; 75865fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa } 7587f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7588f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7589f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameterLength; 7590f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7591f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (queryLength == index) { 7592f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 7593f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7594f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7595f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query.charAt(index) == '=') { 7596f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index++; 7597f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov break; 7598f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7599f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7600f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7601f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int ampIndex = query.indexOf('&', index); 7602f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (ampIndex == -1) { 7603f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index); 7604f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 7605f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index, ampIndex); 7606f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7607f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7608f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return Uri.decode(value); 7609f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 76105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 76110dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov protected boolean isAggregationUpgradeNeeded() { 76120dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 76130dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return false; 76140dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 76150dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 76165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int version = Integer.parseInt(mContactsHelper.getProperty( 76175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROPERTY_AGGREGATION_ALGORITHM, "1")); 76180dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return version < PROPERTY_AGGREGATION_ALGORITHM_VERSION; 76190dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 76200dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 7621bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void upgradeAggregationAlgorithmInBackground() { 76220dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov // This upgrade will affect very few contacts, so it can be performed on the 76230dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov // main thread during the initial boot after an OTA 76240dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 76250dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Log.i(TAG, "Upgrading aggregation algorithm"); 76260dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov int count = 0; 76270dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long start = SystemClock.currentThreadTimeMillis(); 76285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = null; 76290dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov try { 76305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 76315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db = mContactsHelper.getWritableDatabase(); 76325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(db); 76335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.beginTransaction(); 76345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = db.query(true, 76350dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Tables.RAW_CONTACTS + " r1 JOIN " + Tables.RAW_CONTACTS + " r2", 76360dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov new String[]{"r1." + RawContacts._ID}, 76370dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov "r1." + RawContacts._ID + "!=r2." + RawContacts._ID + 76380dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.CONTACT_ID + "=r2." + RawContacts.CONTACT_ID + 76390dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.ACCOUNT_NAME + "=r2." + RawContacts.ACCOUNT_NAME + 764043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND r1." + RawContacts.ACCOUNT_TYPE + "=r2." + RawContacts.ACCOUNT_TYPE + 764143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND r1." + RawContacts.DATA_SET + "=r2." + RawContacts.DATA_SET, 76420dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov null, null, null, null, null); 76430dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov try { 76440dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov while (cursor.moveToNext()) { 76450dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long rawContactId = cursor.getLong(0); 76460dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, 76470dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 76480dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov count++; 76490dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 76500dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } finally { 76510dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov cursor.close(); 76520dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 76535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactAggregator.aggregateInTransaction(mTransactionContext.get(), db); 7654bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 76555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.setTransactionSuccessful(); 76565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setProperty(PROPERTY_AGGREGATION_ALGORITHM, 76570dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov String.valueOf(PROPERTY_AGGREGATION_ALGORITHM_VERSION)); 76580dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } finally { 76595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (db != null) { 76605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.endTransaction(); 76615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 76620dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long end = SystemClock.currentThreadTimeMillis(); 76630dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Log.i(TAG, "Aggregation algorithm upgraded for " + count 76640dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov + " contacts, in " + (end - start) + "ms"); 76650dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 76660dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 76679a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 76689a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov /* Visible for testing */ 76699a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov boolean isPhone() { 76709a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (!sIsPhoneInitialized) { 76719a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sIsPhone = new TelephonyManager(getContext()).isVoiceCapable(); 76729a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sIsPhoneInitialized = true; 76739a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 76749a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return sIsPhone; 76759a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 767646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 767746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private boolean handleDataUsageFeedback(Uri uri) { 767846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final long currentTimeMillis = System.currentTimeMillis(); 767946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String usageType = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 768046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] ids = uri.getLastPathSegment().trim().split(","); 768146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final ArrayList<Long> dataIds = new ArrayList<Long>(); 768246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 768346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa for (String id : ids) { 768446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa dataIds.add(Long.valueOf(id)); 768546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 768646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final boolean successful; 768746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (TextUtils.isEmpty(usageType)) { 768846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Log.w(TAG, "Method for data usage feedback isn't specified. Ignoring."); 768946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa successful = false; 769046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 769146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa successful = updateDataUsageStat(dataIds, usageType, currentTimeMillis) > 0; 769246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 769346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 769446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa // Handle old API. This doesn't affect the result of this entire method. 769546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] questionMarks = new String[ids.length]; 769646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Arrays.fill(questionMarks, "?"); 769746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String where = Data._ID + " IN (" + TextUtils.join(",", questionMarks) + ")"; 76985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final Cursor cursor = mActiveDb.get().query( 7699ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann Views.DATA, 770046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { Data.CONTACT_ID }, 770146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa where, ids, null, null, null); 770246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 770346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa while (cursor.moveToNext()) { 770446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa mSelectionArgs1[0] = cursor.getString(0); 770546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa ContentValues values2 = new ContentValues(); 770646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values2.put(Contacts.LAST_TIME_CONTACTED, currentTimeMillis); 77075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().update(Tables.CONTACTS, values2, Contacts._ID + "=?", 77085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mSelectionArgs1); 77095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 77105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 771146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 771246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 771346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa cursor.close(); 771446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 771546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 771646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return successful; 771746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 771846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 771946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 772046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Update {@link Tables#DATA_USAGE_STAT}. 772146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * 772246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * @return the number of rows affected. 772346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 7724f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa @VisibleForTesting 7725f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa /* package */ int updateDataUsageStat( 7726f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa List<Long> dataIds, String type, long currentTimeMillis) { 772746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final int typeInt = sDataUsageTypeMap.get(type); 772846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String where = DataUsageStatColumns.DATA_ID + " =? AND " 772946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + DataUsageStatColumns.USAGE_TYPE_INT + " =?"; 773046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] columns = 773146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { DataUsageStatColumns._ID, DataUsageStatColumns.TIMES_USED }; 773246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final ContentValues values = new ContentValues(); 773346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa for (Long dataId : dataIds) { 773446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] args = new String[] { dataId.toString(), String.valueOf(typeInt) }; 77355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().beginTransaction(); 773646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 77375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final Cursor cursor = mActiveDb.get().query(Tables.DATA_USAGE_STAT, columns, where, 77385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro args, null, null, null); 773946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 774046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (cursor.getCount() > 0) { 774146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!cursor.moveToFirst()) { 774246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Log.e(TAG, 774346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa "moveToFirst() failed while getAccount() returned non-zero."); 774446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 774546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.clear(); 774646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.TIMES_USED, cursor.getInt(1) + 1); 774746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.LAST_TIME_USED, currentTimeMillis); 77485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().update(Tables.DATA_USAGE_STAT, values, 774946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns._ID + " =?", 775046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { cursor.getString(0) }); 775146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 775246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 775346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.clear(); 775446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.DATA_ID, dataId); 775546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.USAGE_TYPE_INT, typeInt); 775646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.TIMES_USED, 1); 775746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.LAST_TIME_USED, currentTimeMillis); 77585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().insert(Tables.DATA_USAGE_STAT, null, values); 775946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 77605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().setTransactionSuccessful(); 776146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 776246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa cursor.close(); 776346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 776446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 77655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().endTransaction(); 776646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 776746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 776846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 776946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return dataIds.size(); 777046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 777146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 777246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 777346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Returns a sort order String for promoting data rows (email addresses, phone numbers, etc.) 777446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * associated with a primary account. The primary account should be supplied from applications 777546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * with {@link ContactsContract#PRIMARY_ACCOUNT_NAME} and 777646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * {@link ContactsContract#PRIMARY_ACCOUNT_TYPE}. Null will be returned when the primary 777746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * account isn't available. 777846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 777946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private String getAccountPromotionSortOrder(Uri uri) { 778046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String primaryAccountName = 778146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa uri.getQueryParameter(ContactsContract.PRIMARY_ACCOUNT_NAME); 778246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String primaryAccountType = 778346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa uri.getQueryParameter(ContactsContract.PRIMARY_ACCOUNT_TYPE); 778446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 778546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa // Data rows associated with primary account should be promoted. 778646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(primaryAccountName)) { 778746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa StringBuilder sb = new StringBuilder(); 778846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append("(CASE WHEN " + RawContacts.ACCOUNT_NAME + "="); 778946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DatabaseUtils.appendEscapedSQLString(sb, primaryAccountName); 779046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(primaryAccountType)) { 779146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" AND " + RawContacts.ACCOUNT_TYPE + "="); 779246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DatabaseUtils.appendEscapedSQLString(sb, primaryAccountType); 779346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 779446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" THEN 0 ELSE 1 END)"); 779546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return sb.toString(); 779646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 779746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return null; 779846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 779946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 7800b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 7801b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson /** 7802b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * Checks the URI for a deferred snippeting request 7803b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * @return a boolean indicating if a deferred snippeting request is in the RI 7804b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson */ 7805b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private boolean deferredSnippetingRequested(Uri uri) { 7806b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson String deferredSnippeting = 7807b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson getQueryParameter(uri, SearchSnippetColumns.DEFERRED_SNIPPETING_KEY); 7808b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return !TextUtils.isEmpty(deferredSnippeting) && deferredSnippeting.equals("1"); 7809b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 7810b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 7811b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson /** 7812b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * Checks if query is a single word or not. 7813b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * @return a boolean indicating if the query is one word or not 7814b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson */ 7815b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private boolean isSingleWordQuery(String query) { 7816b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return query.split(QUERY_TOKENIZER_REGEX).length == 1; 7817b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 7818b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson 7819b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson /** 7820b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * Checks the projection for a SNIPPET column indicating that a snippet is needed 7821b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson * @return a boolean indicating if a snippet is needed or not. 7822b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson */ 7823b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson private boolean snippetNeeded(String [] projection) { 7824b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson return mDbHelper.get().isInProjection(projection, SearchSnippetColumns.SNIPPET); 7825b3a1271feb57be104aabe8046846da0071a1f23eIsaac Katzenelson } 78264f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 7827