ContactsProvider2.java revision c88cc79e0e19b8299a2a356c7d70b48f70b4a93e
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; 884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 8908ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwoodimport android.database.sqlite.SQLiteDoneException; 905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoroimport android.database.sqlite.SQLiteOpenHelper; 914f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 92f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport android.graphics.Bitmap; 93f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport android.graphics.BitmapFactory; 944f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 95d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.net.Uri.Builder; 96c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoroimport android.os.AsyncTask; 97bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Binder; 986ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.os.Bundle; 99bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Handler; 100bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.HandlerThread; 101bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Message; 102ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringertimport android.os.ParcelFileDescriptor; 103c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoroimport android.os.ParcelFileDescriptor.AutoCloseInputStream; 104bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.os.Process; 105b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 10615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikovimport android.os.StrictMode; 1070dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikovimport android.os.SystemClock; 1080e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 1093d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 110508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 1113de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 112b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 11397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email; 11497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 11597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 11697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 1176d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Note; 11897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 11997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone; 12097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 1214928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.SipAddress; 12297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 12397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 124ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.provider.ContactsContract.ContactCounts; 1253de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 1265b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikovimport android.provider.ContactsContract.Contacts.AggregationSuggestions; 1273de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 12871340347b4862d4b1368a5d69d1667e2245952e4Daisuke Miyakawaimport android.provider.ContactsContract.DataUsageFeedback; 129d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.provider.ContactsContract.Directory; 130f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport android.provider.ContactsContract.DisplayPhoto; 1313de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 132bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.provider.ContactsContract.Intents; 1333de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 1341dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoroimport android.provider.ContactsContract.PhotoFiles; 1350c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoroimport android.provider.ContactsContract.Profile; 13609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.provider.ContactsContract.ProviderStatus; 1373de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 138916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikovimport android.provider.ContactsContract.SearchSnippetColumns; 1393de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 14082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 1413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmannimport android.provider.ContactsContract.StreamItemPhotos; 142f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport android.provider.ContactsContract.StreamItems; 14397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.LiveFolders; 14497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.OpenableColumns; 14597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.SyncStateContract; 146a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 1479a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikovimport android.telephony.TelephonyManager; 148a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 149c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1504f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 151108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawaimport java.io.BufferedWriter; 152d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 153f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoroimport java.io.File; 154b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 155d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 156d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 157108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawaimport java.io.OutputStreamWriter; 158108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawaimport java.io.Writer; 15942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.text.SimpleDateFormat; 1607e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 16146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawaimport java.util.Arrays; 1625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 16342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.util.Date; 164b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1650e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 167622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 168b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1690e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 170ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1714f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1724f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 1765b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanapublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener { 177caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 178bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 179bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 180bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 18215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_INITIALIZE = 0; 18315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_OPEN_WRITE_ACCESS = 1; 18415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS = 2; 18515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_ACCOUNTS = 3; 18615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_LOCALE = 4; 18715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final int BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM = 5; 18805e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_SEARCH_INDEX = 6; 18905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_PROVIDER_STATUS = 7; 19005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_UPDATE_DIRECTORIES = 8; 19105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int BACKGROUND_TASK_CHANGE_LOCALE = 9; 192f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int BACKGROUND_TASK_CLEANUP_PHOTOS = 10; 193619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** Limit for the maximum number of social stream items to store under a raw contact. */ 1983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int MAX_STREAM_ITEMS_PER_RAW_CONTACT = 5; 1993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 200f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** Rate limit (in ms) for photo cleanup. Do it at most once per day. */ 201f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int PHOTO_CLEANUP_RATE_LIMIT = 24 * 60 * 60 * 1000; 202f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 2033d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 204b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov * Property key for the legacy contact import version. The need for a version 2053d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 2063d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 2073d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 208b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final String PROPERTY_CONTACTS_IMPORTED = "contacts_imported_v1"; 209b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final int PROPERTY_CONTACTS_IMPORT_VERSION = 1; 21051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov private static final String PREF_LOCALE = "locale"; 2113d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2120dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static final String PROPERTY_AGGREGATION_ALGORITHM = "aggregation_v2"; 2130dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static final int PROPERTY_AGGREGATION_ALGORITHM_VERSION = 2; 2140dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 2150e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 2160e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 2175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final ProfileAwareUriMatcher sUriMatcher = 2185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ProfileAwareUriMatcher(UriMatcher.NO_MATCH); 2194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2202f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa /** 2212f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa * Used to insert a column into strequent results, which enables SQL to sort the list using 2222f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa * the total times contacted. See also {@link #sStrequentFrequentProjectionMap}. 2232f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa */ 2242f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa private static final String TIMES_USED_SORT_COLUMN = "times_used_sort"; 2255e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 226d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 2272f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa + TIMES_USED_SORT_COLUMN + " DESC, " 2289b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 229d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 230d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 231d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 232d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 23345ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa private static final String FREQUENT_ORDER_BY = DataUsageStatColumns.TIMES_USED + " DESC," 23445ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 23545ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa 2366e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_CONTACTS_TABLE = 2379b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.CONTACTS + " SET " + Contacts.TIMES_CONTACTED + "=" + 2389b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + Contacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 2399b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + Contacts.TIMES_CONTACTED + " + 1) END WHERE " + Contacts._ID + "=?"; 2409b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 2416e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE = 2429b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.RAW_CONTACTS + " SET " + RawContacts.TIMES_CONTACTED + "=" + 2439b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + RawContacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 2449b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + RawContacts.TIMES_CONTACTED + " + 1) END WHERE " + RawContacts.CONTACT_ID + "=?"; 2459b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 246de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa /* package */ static final String PHONEBOOK_COLLATOR_NAME = "PHONEBOOK"; 247de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa 2483716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Regex for splitting query strings - we split on any group of non-alphanumeric characters, 2493716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // excluding the @ symbol. 2503716f1447ceb21180d1301790eabd8b9453f486dDave Santoro /* package */ static final String QUERY_TOKENIZER_REGEX = "[^\\w@]+"; 2513716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 252d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 253d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 2545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 2555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 256a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_DATA = 1004; 2575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 2585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 2595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 2605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 261a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int CONTACTS_ID_PHOTO = 1009; 262f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_ID_DISPLAY_PHOTO = 1010; 263f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_LOOKUP_DISPLAY_PHOTO = 1011; 264f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_LOOKUP_ID_DISPLAY_PHOTO = 1012; 265f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_AS_VCARD = 1013; 266f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_AS_MULTI_VCARD = 1014; 267f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_LOOKUP_DATA = 1015; 268f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_LOOKUP_ID_DATA = 1016; 269f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_ID_ENTITIES = 1017; 270f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_LOOKUP_ENTITIES = 1018; 271f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_LOOKUP_ID_ENTITIES = 1019; 272f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_ID_STREAM_ITEMS = 1020; 273f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_LOOKUP_STREAM_ITEMS = 1021; 274f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int CONTACTS_LOOKUP_ID_STREAM_ITEMS = 1022; 27545ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa private static final int CONTACTS_FREQUENT = 1023; 2764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 2785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 2795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 28046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 281f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int RAW_CONTACTS_ID_DISPLAY_PHOTO = 2006; 282f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int RAW_CONTACTS_ID_STREAM_ITEMS = 2007; 28382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro private static final int RAW_CONTACTS_ID_STREAM_ITEMS_ID = 2008; 2844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2856bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 2866bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 287ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 28848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 28948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 29048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 29148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 29248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 29348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 29448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 29548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 296a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2976bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 2986bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 299b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 300b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 301b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 30282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 30382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 3041f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 30531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 30631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 307eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 308eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 309ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 310ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 311ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 312ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 31335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 314b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 3155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final int PROFILE_SYNCSTATE = 11002; 3165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final int PROFILE_SYNCSTATE_ID = 11003; 31735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 318c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 319c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 320c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3211b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 3221b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 3231b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 3241b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 3251b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 32646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 32746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 32809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private static final int PROVIDER_STATUS = 16001; 32909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 330d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES = 17001; 331d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final int DIRECTORIES_ID = 17002; 332d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3337a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private static final int COMPLETE_NAME = 18000; 3347a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 33524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE = 19000; 33624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_ENTITIES = 19001; 33724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_DATA = 19002; 33824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_DATA_ID = 19003; 33924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_AS_VCARD = 19004; 34024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS = 19005; 34124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID = 19006; 34224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID_DATA = 19007; 34324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private static final int PROFILE_RAW_CONTACTS_ID_ENTITIES = 19008; 3445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final int PROFILE_STATUS_UPDATES = 19009; 34524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 34646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final int DATA_USAGE_FEEDBACK_ID = 20001; 34746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 3483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS = 21000; 3493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_PHOTOS = 21001; 3503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID = 21002; 3513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID_PHOTOS = 21003; 3523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_ID_PHOTOS_ID = 21004; 3533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final int STREAM_ITEMS_LIMIT = 21005; 3543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 355f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int DISPLAY_PHOTO = 22000; 356f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private static final int PHOTO_DIMENSIONS = 22001; 357f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 3585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Inserts into URIs in this map will direct to the profile database if the parent record's 3595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // value (looked up from the ContentValues object with the key specified by the value in this 3605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // map) is in the profile ID-space (see {@link ProfileDatabaseHelper#PROFILE_ID_SPACE}). 3615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private static final Map<Integer, String> INSERT_URI_ID_VALUE_MAP = Maps.newHashMap(); 3625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro static { 3635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(DATA, Data.RAW_CONTACT_ID); 3645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(RAW_CONTACTS_DATA, Data.RAW_CONTACT_ID); 3655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STATUS_UPDATES, StatusUpdates.DATA_ID); 3665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STREAM_ITEMS, StreamItems.RAW_CONTACT_ID); 3675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(RAW_CONTACTS_ID_STREAM_ITEMS, StreamItems.RAW_CONTACT_ID); 3685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STREAM_ITEMS_PHOTOS, StreamItemPhotos.STREAM_ITEM_ID); 3695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro INSERT_URI_ID_VALUE_MAP.put(STREAM_ITEMS_ID_PHOTOS, StreamItemPhotos.STREAM_ITEM_ID); 3705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 3715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 372dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID = 373dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 374dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME 375dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 376dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE 37743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + "=" + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AND (" 37843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET 37943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + "=" + RawContactsColumns.CONCRETE_DATA_SET + " OR " 38043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET + " IS NULL AND " 38143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_DATA_SET + " IS NULL)" 382dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND " + Groups.FAVORITES + " != 0"; 383dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 384dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID = 385dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 386dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 387dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 388dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 38943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AND (" 39043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET + "=" 39143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_DATA_SET + " OR " 39243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + GroupsColumns.CONCRETE_DATA_SET + " IS NULL AND " 39343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContactsColumns.CONCRETE_DATA_SET + " IS NULL)" 39443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + " AND " + Groups.AUTO_ADD + " != 0"; 395dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 396dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String[] PROJECTION_GROUP_ID 397dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana = new String[]{Tables.GROUPS + "." + Groups._ID}; 398dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 399dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_GROUPMEMBERSHIP_DATA = DataColumns.MIMETYPE_ID + "=? " 400dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.GROUP_ROW_ID + "=? " 401dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.RAW_CONTACT_ID + "=?"; 402dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 403dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_STARRED_FROM_RAW_CONTACTS = 404dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana "SELECT " + RawContacts.STARRED 405dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?"; 406dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 407d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 408f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 409f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 410f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 41167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 41267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 4136cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 4146802030a777c0c3ba1dc029c534cca4784260632Dave Santoro RawContactsColumns.CONCRETE_ACCOUNT_TYPE, 4156802030a777c0c3ba1dc029c534cca4784260632Dave Santoro RawContactsColumns.CONCRETE_ACCOUNT_NAME, 41643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContactsColumns.CONCRETE_DATA_SET, 4173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 418f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 419ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 420ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 421d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 4226802030a777c0c3ba1dc029c534cca4784260632Dave Santoro public static final int ACCOUNT_TYPE = 1; 4236802030a777c0c3ba1dc029c534cca4784260632Dave Santoro public static final int ACCOUNT_NAME = 2; 42443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro public static final int DATA_SET = 3; 42543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro public static final int DATA_ID = 4; 42643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro public static final int CONTACT_ID = 5; 427ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4281f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 429f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov interface RawContactsQuery { 43019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 43119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 43219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 433ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.DELETED, 434ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 435ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_NAME, 43643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.DATA_SET, 43719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 43819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 43919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 440ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_TYPE = 1; 441ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_NAME = 2; 44243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int DATA_SET = 3; 44319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 44419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 445c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 446caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 44771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 44871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 44971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 45071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 45171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 45271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 45371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 45471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 45571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 45671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 45771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 45871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 45971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 46071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 461a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating DIRTY flag on multiple raw contacts */ 462a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_DIRTY_SQL = 463a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 464a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.DIRTY + "=1" + 465a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 466a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 467a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating VERSION on multiple raw contacts */ 468a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_VERSION_SQL = 469a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 470a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + 471a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 472a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 473c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov // Current contacts - those contacted within the last 3 days (in seconds) 474c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final long EMAIL_FILTER_CURRENT = 3 * 24 * 60 * 60; 475c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 476c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov // Recent contacts - those contacted within the last 30 days (in seconds) 477c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final long EMAIL_FILTER_RECENT = 30 * 24 * 60 * 60; 478c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 479f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa private static final String TIME_SINCE_LAST_USED = 480f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa "(strftime('%s', 'now') - " + DataUsageStatColumns.LAST_TIME_USED + "/1000)"; 481f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa 482c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov /* 483c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * Sorting order for email address suggestions: first starred, then the rest. 4842262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * second in_visible_group, then the rest. 4852262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * Within the four (starred/unstarred, in_visible_group/not-in_visible_group) groups 4862262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa * - three buckets: very recently contacted, then fairly 487c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov * recently contacted, then the rest. Within each of the bucket - descending count 48846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * of times contacted (both for data row and for contact row). If all else fails, alphabetical. 48946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * (Super)primary email address is returned before other addresses for the same contact. 490c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov */ 491c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov private static final String EMAIL_FILTER_SORT_ORDER = 4922262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa Contacts.STARRED + " DESC, " 4932262f0ccc800b93a9d1e63c55654ca3aaf5e7d1cDaisuke Miyakawa + Contacts.IN_VISIBLE_GROUP + " DESC, " 494f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa + "(CASE WHEN " + TIME_SINCE_LAST_USED + " < " + EMAIL_FILTER_CURRENT 49546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " THEN 0 " 496f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa + " WHEN " + TIME_SINCE_LAST_USED + " < " + EMAIL_FILTER_RECENT 49746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " THEN 1 " 49846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + " ELSE 2 END), " 49946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + DataUsageStatColumns.TIMES_USED + " DESC, " 50046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + Contacts.DISPLAY_NAME + ", " 50146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + Data.CONTACT_ID + ", " 502c591cc2ffecdd0038f787a133606752752294c13Daisuke Miyakawa + Data.IS_SUPER_PRIMARY + " DESC, " 503c591cc2ffecdd0038f787a133606752752294c13Daisuke Miyakawa + Data.IS_PRIMARY + " DESC"; 50446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 50546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** Currently same as {@link #EMAIL_FILTER_SORT_ORDER} */ 50646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final String PHONE_FILTER_SORT_ORDER = EMAIL_FILTER_SORT_ORDER; 507c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 508916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Name lookup types used for contact filtering */ 509916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final String CONTACT_LOOKUP_NAME_TYPES = 510916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_COLLATION_KEY + "," + 511916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME + "," + 51292ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov NameLookupType.NICKNAME; 513916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 514f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov /** 515f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov * If any of these columns are used in a Data projection, there is no point in 516f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov * using the DISTINCT keyword, which can negatively affect performance. 517f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov */ 518f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov private static final String[] DISTINCT_DATA_PROHIBITING_COLUMNS = { 519f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data._ID, 520f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data.RAW_CONTACT_ID, 521f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov Data.NAME_RAW_CONTACT_ID, 522f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 523f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 52443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.DATA_SET, 52543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 526f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.DIRTY, 527f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.NAME_VERIFIED, 528f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.SOURCE_ID, 529f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.VERSION, 530f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov }; 531916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 532f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsColumns = ProjectionMap.builder() 533f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CUSTOM_RINGTONE) 534f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME) 535f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_ALTERNATIVE) 536f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.DISPLAY_NAME_SOURCE) 537f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.IN_VISIBLE_GROUP) 538f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LAST_TIME_CONTACTED) 539f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.LOOKUP_KEY) 540f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME) 541f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHONETIC_NAME_STYLE) 542f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.PHOTO_ID) 543f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .add(Contacts.PHOTO_FILE_ID) 5443d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(Contacts.PHOTO_URI) 5453d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(Contacts.PHOTO_THUMBNAIL_URI) 546f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SEND_TO_VOICEMAIL) 547f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_ALTERNATIVE) 548f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.SORT_KEY_PRIMARY) 549f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.STARRED) 550f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.TIMES_CONTACTED) 551cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 552f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 553f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 554f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsPresenceColumns = ProjectionMap.builder() 555f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 556f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE) 557f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 558f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 559f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 560f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 561f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 562f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 563f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 564f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 565f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 566f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 567f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 568f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 569f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 570f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 571f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSnippetColumns = ProjectionMap.builder() 57203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov .add(SearchSnippetColumns.SNIPPET) 573f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 574f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 575f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactColumns = ProjectionMap.builder() 576f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_NAME) 577f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.ACCOUNT_TYPE) 57843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(RawContacts.DATA_SET) 57943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(RawContacts.ACCOUNT_TYPE_AND_DATA_SET) 580f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DIRTY) 581f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.NAME_VERIFIED) 582f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SOURCE_ID) 583f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.VERSION) 584f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 585f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 586f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactSyncColumns = ProjectionMap.builder() 587f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC1) 588f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC2) 589f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC3) 590f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SYNC4) 591f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 592f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 593f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataColumns = ProjectionMap.builder() 594f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA1) 595f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA2) 596f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA3) 597f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA4) 598f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA5) 599f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA6) 600f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA7) 601f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA8) 602f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA9) 603f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA10) 604f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA11) 605f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA12) 606f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA13) 607f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA14) 608f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA15) 609f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.DATA_VERSION) 610f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_PRIMARY) 611f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.IS_SUPER_PRIMARY) 612f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.MIMETYPE) 613f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RES_PACKAGE) 614f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC1) 615f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC2) 616f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC3) 617f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.SYNC4) 618f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(GroupMembership.GROUP_SOURCE_ID) 619f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 620f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 621f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactPresenceColumns = ProjectionMap.builder() 622f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_PRESENCE, 623f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.PRESENCE) 624f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_CHAT_CAPABILITY, 625f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + '.' + StatusUpdates.CHAT_CAPABILITY) 626f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS, 627f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS) 628f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_TIMESTAMP, 629f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 630f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_RES_PACKAGE, 631f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 632f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_LABEL, 633f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL) 634f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.CONTACT_STATUS_ICON, 635f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON) 636f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 637f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 638f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataPresenceColumns = ProjectionMap.builder() 639f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.PRESENCE, Tables.PRESENCE + "." + StatusUpdates.PRESENCE) 640f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CHAT_CAPABILITY, Tables.PRESENCE + "." + StatusUpdates.CHAT_CAPABILITY) 641f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS, StatusUpdatesColumns.CONCRETE_STATUS) 642f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_TIMESTAMP, StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP) 643f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_RES_PACKAGE, StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE) 644f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_LABEL, StatusUpdatesColumns.CONCRETE_STATUS_LABEL) 645f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.STATUS_ICON, StatusUpdatesColumns.CONCRETE_STATUS_ICON) 646f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 647f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 648038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 649f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sCountProjectionMap = ProjectionMap.builder() 650f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(BaseColumns._COUNT, "COUNT(*)") 651f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 652f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 653e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 654f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionMap = ProjectionMap.builder() 655f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts._ID) 656f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.HAS_PHONE_NUMBER) 657f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.NAME_RAW_CONTACT_ID) 65824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(Contacts.IS_USER_PROFILE) 659f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 660f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsPresenceColumns) 661f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 662f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 663916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Contains just the contacts columns */ 664f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsProjectionWithSnippetMap = ProjectionMap.builder() 665f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 666f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sSnippetColumns) 667f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 668916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 6695e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 670f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentStarredProjectionMap = ProjectionMap.builder() 671f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 6722f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, String.valueOf(Long.MAX_VALUE)) 673f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 674f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 675f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStrequentFrequentProjectionMap = ProjectionMap.builder() 676f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsProjectionMap) 6772f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, "SUM(" + DataUsageStatColumns.CONCRETE_TIMES_USED + ")") 678f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 679f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 6804928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa /** 6814928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * Used for Strequent Uri with {@link ContactsContract#STREQUENT_PHONE_ONLY}, which allows 6824928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * users to obtain part of Data columns. Right now Starred part just returns NULL for 6834928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * those data columns (frequent part should return real ones in data table). 6844928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa **/ 6854928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa private static final ProjectionMap sStrequentPhoneOnlyStarredProjectionMap 6864928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa = ProjectionMap.builder() 6874928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .addAll(sContactsProjectionMap) 6884928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, String.valueOf(Long.MAX_VALUE)) 6894928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.NUMBER, "NULL") 6904928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.TYPE, "NULL") 6914928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.LABEL, "NULL") 6924928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .build(); 6934928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 6944928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa /** 6954928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * Used for Strequent Uri with {@link ContactsContract#STREQUENT_PHONE_ONLY}, which allows 6964928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * users to obtain part of Data columns. We hard-code {@link Contacts#IS_USER_PROFILE} to NULL, 6974928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * because sContactsProjectionMap specifies a field that doesn't exist in the view behind the 6984928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * query that uses this projection map. 6994928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa **/ 7004928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa private static final ProjectionMap sStrequentPhoneOnlyFrequentProjectionMap 7014928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa = ProjectionMap.builder() 7024928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .addAll(sContactsProjectionMap) 7034928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(TIMES_USED_SORT_COLUMN, DataUsageStatColumns.CONCRETE_TIMES_USED) 7044928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.NUMBER) 7054928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.TYPE) 7064928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Phone.LABEL) 7074928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .add(Contacts.IS_USER_PROFILE, "NULL") 7084928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa .build(); 7094928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 710f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 711f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sContactsVCardProjectionMap = ProjectionMap.builder() 712fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen .add(Contacts._ID) 713f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME + " || '.vcf'") 714f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(OpenableColumns.SIZE, "NULL") 715f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 716f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 717ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 718f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawContactsProjectionMap = ProjectionMap.builder() 719f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 720f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 721f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 722f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_PRIMARY) 723f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_ALTERNATIVE) 724f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DISPLAY_NAME_SOURCE) 725f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME) 726f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.PHONETIC_NAME_STYLE) 727f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_PRIMARY) 728f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SORT_KEY_ALTERNATIVE) 729f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.TIMES_CONTACTED) 730f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.LAST_TIME_CONTACTED) 731f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CUSTOM_RINGTONE) 732f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.SEND_TO_VOICEMAIL) 733f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 734f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.AGGREGATION_MODE) 73524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 736f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 737f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 738f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 739f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 740a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the raw entity view*/ 741f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sRawEntityProjectionMap = ProjectionMap.builder() 742f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts._ID) 743f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 744f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.Entity.DATA_ID) 745f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.DELETED) 746f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.STARRED) 74724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 748f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 749f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 750f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 751f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 752f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 753a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** Contains the columns from the contact entity view*/ 754f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sEntityProjectionMap = ProjectionMap.builder() 755f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity._ID) 756f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.CONTACT_ID) 757f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.RAW_CONTACT_ID) 758f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DATA_ID) 759f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.NAME_RAW_CONTACT_ID) 760f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Contacts.Entity.DELETED) 76124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(Contacts.IS_USER_PROFILE) 762f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 763f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 764f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 765f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactSyncColumns) 766f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 767f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 768f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 769f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 771f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDataProjectionMap = ProjectionMap.builder() 772f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID) 773f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.RAW_CONTACT_ID) 774f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.CONTACT_ID) 775f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data.NAME_RAW_CONTACT_ID) 77624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 777f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 778f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 779f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sRawContactColumns) 780f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 781f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 782f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 783f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 785f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDistinctDataProjectionMap = ProjectionMap.builder() 786f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Data._ID, "MIN(" + Data._ID + ")") 787f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(RawContacts.CONTACT_ID) 78824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro .add(RawContacts.RAW_CONTACT_IS_USER_PROFILE) 789f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataColumns) 790f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sDataPresenceColumns) 791f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactsColumns) 792f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sContactPresenceColumns) 793f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 794f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 7959261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 796f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sPhoneLookupProjectionMap = ProjectionMap.builder() 797f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup._ID, "contacts_view." + Contacts._ID) 798f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LOOKUP_KEY, "contacts_view." + Contacts.LOOKUP_KEY) 799f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.DISPLAY_NAME, "contacts_view." + Contacts.DISPLAY_NAME) 800f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LAST_TIME_CONTACTED, "contacts_view." + Contacts.LAST_TIME_CONTACTED) 801f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TIMES_CONTACTED, "contacts_view." + Contacts.TIMES_CONTACTED) 802f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.STARRED, "contacts_view." + Contacts.STARRED) 803f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.IN_VISIBLE_GROUP, "contacts_view." + Contacts.IN_VISIBLE_GROUP) 804f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.PHOTO_ID, "contacts_view." + Contacts.PHOTO_ID) 8053d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(PhoneLookup.PHOTO_URI, "contacts_view." + Contacts.PHOTO_URI) 8063d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov .add(PhoneLookup.PHOTO_THUMBNAIL_URI, "contacts_view." + Contacts.PHOTO_THUMBNAIL_URI) 807f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.CUSTOM_RINGTONE, "contacts_view." + Contacts.CUSTOM_RINGTONE) 808f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.HAS_PHONE_NUMBER, "contacts_view." + Contacts.HAS_PHONE_NUMBER) 809f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.SEND_TO_VOICEMAIL, "contacts_view." + Contacts.SEND_TO_VOICEMAIL) 810f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.NUMBER, Phone.NUMBER) 811f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.TYPE, Phone.TYPE) 812f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PhoneLookup.LABEL, Phone.LABEL) 8132530512f639c4979fd7371c7dd25dd67e8118124Bai Tao .add(PhoneLookup.NORMALIZED_NUMBER, Phone.NORMALIZED_NUMBER) 814f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 815f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 816ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 817f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsProjectionMap = ProjectionMap.builder() 818f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups._ID) 819f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_NAME) 820f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.ACCOUNT_TYPE) 82143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(Groups.DATA_SET) 82243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .add(Groups.ACCOUNT_TYPE_AND_DATA_SET) 823f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SOURCE_ID) 824f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DIRTY) 825f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.VERSION) 826f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.RES_PACKAGE) 827f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE) 828f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.TITLE_RES) 829f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.GROUP_VISIBLE) 830f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYSTEM_ID) 831f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.DELETED) 832f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.NOTES) 833f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SHOULD_SYNC) 834f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.FAVORITES) 835f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.AUTO_ADD) 836c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov .add(Groups.GROUP_IS_READ_ONLY) 837f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC1) 838f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC2) 839f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC3) 840f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SYNC4) 841f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 842f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 843ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 844f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sGroupsSummaryProjectionMap = ProjectionMap.builder() 845f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .addAll(sGroupsProjectionMap) 846f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_COUNT, 847f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa "(SELECT COUNT(" + ContactsColumns.CONCRETE_ID + ") FROM " 848f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Tables.CONTACTS_JOIN_RAW_CONTACTS_DATA_FILTERED_BY_GROUPMEMBERSHIP 849f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + ")") 850f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Groups.SUMMARY_WITH_PHONES, 851f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa "(SELECT COUNT(" + ContactsColumns.CONCRETE_ID + ") FROM " 852f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Tables.CONTACTS_JOIN_RAW_CONTACTS_DATA_FILTERED_BY_GROUPMEMBERSHIP 853f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " WHERE " + Contacts.HAS_PHONE_NUMBER + ")") 854f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa .build(); 855f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa 856f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa // This is only exposed as hidden API for the contacts app, so we can be very specific in 857f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa // the filtering 858f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa private static final ProjectionMap sGroupsSummaryProjectionMapWithGroupCountPerAccount = 859f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa ProjectionMap.builder() 860f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa .addAll(sGroupsSummaryProjectionMap) 861f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa .add(Groups.SUMMARY_GROUP_COUNT_PER_ACCOUNT, 862f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa "(SELECT COUNT(*) FROM " + Views.GROUPS + " WHERE " 863f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + "(" + Groups.ACCOUNT_NAME + "=" 864f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + GroupsColumns.CONCRETE_ACCOUNT_NAME 865f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " AND " 866f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.ACCOUNT_TYPE + "=" + GroupsColumns.CONCRETE_ACCOUNT_TYPE 867f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " AND " 868f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.DELETED + "=0 AND " 869f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.FAVORITES + "=0 AND " 870f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.AUTO_ADD + "=0" 871f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + ")" 872f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + " GROUP BY " 873f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + Groups.ACCOUNT_NAME + ", " + Groups.ACCOUNT_TYPE 874f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa + ")") 875f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 876f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 877373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 878f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sAggregationExceptionsProjectionMap = ProjectionMap.builder() 879f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id") 880f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.TYPE) 881f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID1) 882f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(AggregationExceptions.RAW_CONTACT_ID2) 883f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 884f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 885eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 886f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sSettingsProjectionMap = ProjectionMap.builder() 887f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_NAME) 888f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ACCOUNT_TYPE) 889f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_VISIBLE) 890f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.SHOULD_SYNC) 891f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.ANY_UNSYNCED, 892f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 893f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ",(SELECT " 894f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "(CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL" 895f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 896f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE MIN(" + Groups.SHOULD_SYNC + ")" 897f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)" 898f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.GROUPS 899f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 900f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + SettingsColumns.CONCRETE_ACCOUNT_NAME 901f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 902f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0" 903f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN 1" 904f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE 0" 905f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " END)") 906f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_COUNT, 907f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 908f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 909f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 910f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 911f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 912f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 913f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Settings.UNGROUPED_WITH_PHONES, 914f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(SELECT COUNT(*)" 915f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM (SELECT 1" 916f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " FROM " + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS 917f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " WHERE " + Contacts.HAS_PHONE_NUMBER 918f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 919f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS 920f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "))") 921f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 922f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 92382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 924f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sStatusUpdatesProjectionMap = ProjectionMap.builder() 925f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(PresenceColumns.RAW_CONTACT_ID) 926f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.DATA_ID, DataColumns.CONCRETE_ID) 927f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_ACCOUNT) 928f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.IM_HANDLE) 929f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PROTOCOL) 930f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 931f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // properly enforce uniqueness of null values 932f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CUSTOM_PROTOCOL, 933f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL + "=''" 934f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " THEN NULL" 935f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END)") 936f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.PRESENCE) 937f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.CHAT_CAPABILITY) 938f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS) 939f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_TIMESTAMP) 940f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_RES_PACKAGE) 941f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_ICON) 942f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(StatusUpdates.STATUS_LABEL) 943f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 944f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 9453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** Contains StreamItems columns */ 9463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final ProjectionMap sStreamItemsProjectionMap = ProjectionMap.builder() 9479b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems._ID) 9489b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.CONTACT_ID) 949af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann .add(StreamItems.CONTACT_LOOKUP_KEY) 9509b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.ACCOUNT_NAME) 9519b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.ACCOUNT_TYPE) 9529b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.DATA_SET) 9533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RAW_CONTACT_ID) 9549b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann .add(StreamItems.RAW_CONTACT_SOURCE_ID) 9553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_PACKAGE) 9563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_ICON) 9573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RES_LABEL) 9583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.TEXT) 9593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.TIMESTAMP) 9603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.COMMENTS) 9610bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC1) 9620bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC2) 9630bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC3) 9640bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.SYNC4) 9653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .build(); 9663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 9673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private static final ProjectionMap sStreamItemPhotosProjectionMap = ProjectionMap.builder() 9683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos._ID, StreamItemPhotosColumns.CONCRETE_ID) 9693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItems.RAW_CONTACT_ID) 9700bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItems.RAW_CONTACT_SOURCE_ID, RawContactsColumns.CONCRETE_SOURCE_ID) 9713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos.STREAM_ITEM_ID) 9723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .add(StreamItemPhotos.SORT_INDEX) 9736802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .add(StreamItemPhotos.PHOTO_FILE_ID) 9746802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .add(StreamItemPhotos.PHOTO_URI, 9756802030a777c0c3ba1dc029c534cca4784260632Dave Santoro "'" + DisplayPhoto.CONTENT_URI + "'||'/'||" + StreamItemPhotos.PHOTO_FILE_ID) 9761dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro .add(PhotoFiles.HEIGHT) 9771dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro .add(PhotoFiles.WIDTH) 9781dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro .add(PhotoFiles.FILESIZE) 9790bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC1) 9800bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC2) 9810bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC3) 9820bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann .add(StreamItemPhotos.SYNC4) 9833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann .build(); 9843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 9851b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 986f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sLiveFoldersProjectionMap = ProjectionMap.builder() 987f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(LiveFolders._ID, Contacts._ID) 988f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(LiveFolders.NAME, Contacts.DISPLAY_NAME) 989f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 990f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // for contacts without a photo 991f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // .add(LiveFolders.ICON_BITMAP, Photos.DATA) 992f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 993f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 994d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** Contains {@link Directory} columns */ 995f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov private static final ProjectionMap sDirectoryProjectionMap = ProjectionMap.builder() 996f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory._ID) 997f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.PACKAGE_NAME) 998f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.TYPE_RESOURCE_ID) 999f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DISPLAY_NAME) 1000f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.DIRECTORY_AUTHORITY) 1001f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_TYPE) 1002f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.ACCOUNT_NAME) 1003f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .add(Directory.EXPORT_SUPPORT) 1004778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov .add(Directory.SHORTCUT_SUPPORT) 1005778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov .add(Directory.PHOTO_SUPPORT) 1006f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov .build(); 10077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 10089705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // where clause to update the status_updates table 10099705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 10109705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 10119705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 10129705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 10139705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 10142526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private static final String[] EMPTY_STRING_ARRAY = new String[0]; 10152526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 1016bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1017bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Notification ID for failure to import contacts. 1018bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1019bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private static final int LEGACY_IMPORT_FAILED_NOTIFICATION = 1; 102051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 102103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_START_MATCH = "["; 102203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_END_MATCH = "]"; 102303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final String DEFAULT_SNIPPET_ARG_ELLIPSIS = "..."; 102403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static final int DEFAULT_SNIPPET_ARG_MAX_TOKENS = -10; 102503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 10269a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov private boolean sIsPhoneInitialized; 10279a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov private boolean sIsPhone; 10289a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 1029f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 10301129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 10311129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs2 = new String[2]; 10322526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private ArrayList<String> mSelectionArgs = Lists.newArrayList(); 10332526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 1034f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private Account mAccount; 1035f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 103646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 103746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Stores mapping from type Strings exposed via {@link DataUsageFeedback} to 103846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * type integers in {@link DataUsageStatColumns}. 103946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 104046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private static final Map<String, Integer> sDataUsageTypeMap; 104146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 10424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 10434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 1044a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 1045d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 1046d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 1047a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_ID_DATA); 1048a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/entities", CONTACTS_ID_ENTITIES); 10493653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 10503653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 10512d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 10522d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 1053a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_ID_PHOTO); 1054f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/display_photo", 1055f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro CONTACTS_ID_DISPLAY_PHOTO); 10563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/stream_items", 10573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_ID_STREAM_ITEMS); 1058c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter", CONTACTS_FILTER); 10595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 10605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 10612149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/data", CONTACTS_LOOKUP_DATA); 10625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 10632149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/data", 10642149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov CONTACTS_LOOKUP_ID_DATA); 1065f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/display_photo", 1066f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro CONTACTS_LOOKUP_DISPLAY_PHOTO); 1067f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/display_photo", 1068f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro CONTACTS_LOOKUP_ID_DISPLAY_PHOTO); 1069a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/entities", 1070a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ENTITIES); 1071a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/entities", 1072a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov CONTACTS_LOOKUP_ID_ENTITIES); 10733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/stream_items", 10743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_LOOKUP_STREAM_ITEMS); 10753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/stream_items", 10763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann CONTACTS_LOOKUP_ID_STREAM_ITEMS); 1077f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 107842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_multi_vcard/*", 107942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann CONTACTS_AS_MULTI_VCARD); 10805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 1081ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 1082ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 10835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 108445ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa matcher.addURI(ContactsContract.AUTHORITY, "contacts/frequent", CONTACTS_FREQUENT); 10853653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 10865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 10875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 10885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 1089f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/display_photo", 1090f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro RAW_CONTACTS_ID_DISPLAY_PHOTO); 109146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 10923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/stream_items", 10933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann RAW_CONTACTS_ID_STREAM_ITEMS); 109482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/stream_items/#", 109582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro RAW_CONTACTS_ID_STREAM_ITEMS_ID); 109646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 109746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 1098b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 10994f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 11004f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 1101ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 110248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 11035e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 1104ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 11054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 110648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 11071dac83b8fa58944acfd00f44e717a7dddc659d2dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup", EMAILS_LOOKUP); 11085e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 11095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 11104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 1111ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 111248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 111346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** "*" is in CSV form with data ids ("123,456,789") */ 111446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa matcher.addURI(ContactsContract.AUTHORITY, "data/usagefeedback/*", DATA_USAGE_FEEDBACK_ID); 11151f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1116ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 1117ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 1118ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 1119ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 112035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 1121b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 1122b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 11235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/" + SyncStateContentProviderHelper.PATH, 11245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROFILE_SYNCSTATE); 11255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, 11265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro "profile/" + SyncStateContentProviderHelper.PATH + "/#", 11275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROFILE_SYNCSTATE_ID); 112835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1129a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 1130b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 1131b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 1132b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 1133b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 11344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1135eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 1136eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 113782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 113882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 11391f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1140c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 1141c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 1142c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 1143c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 11442d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", 1145c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 1146c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 11471b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 11481b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 11491b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 11501b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 11511b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 11521b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 11531b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 11541b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 115509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 115609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "provider_status", PROVIDER_STATUS); 1157d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 1158d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories", DIRECTORIES); 1159d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "directories/#", DIRECTORIES_ID); 11607a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 11617a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "complete_name", COMPLETE_NAME); 116224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 116324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile", PROFILE); 116424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/entities", PROFILE_ENTITIES); 116524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/data", PROFILE_DATA); 116624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/data/#", PROFILE_DATA_ID); 116724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/as_vcard", PROFILE_AS_VCARD); 116824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts", PROFILE_RAW_CONTACTS); 116924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#", 117024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID); 117124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#/data", 117224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID_DATA); 117324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/raw_contacts/#/entity", 117424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro PROFILE_RAW_CONTACTS_ID_ENTITIES); 11755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "profile/status_updates", 11765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROFILE_STATUS_UPDATES); 117746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 11783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items", STREAM_ITEMS); 11793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/photo", STREAM_ITEMS_PHOTOS); 11803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#", STREAM_ITEMS_ID); 11813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#/photo", STREAM_ITEMS_ID_PHOTOS); 11823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items/#/photo/#", 11833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann STREAM_ITEMS_ID_PHOTOS_ID); 11843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "stream_items_limit", STREAM_ITEMS_LIMIT); 11853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 11865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "display_photo/#", DISPLAY_PHOTO); 1187f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro matcher.addURI(ContactsContract.AUTHORITY, "photo_dimensions", PHOTO_DIMENSIONS); 1188f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 118946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa HashMap<String, Integer> tmpTypeMap = new HashMap<String, Integer>(); 119046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_CALL, DataUsageStatColumns.USAGE_TYPE_INT_CALL); 119146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_LONG_TEXT, 119246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns.USAGE_TYPE_INT_LONG_TEXT); 119346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa tmpTypeMap.put(DataUsageFeedback.USAGE_TYPE_SHORT_TEXT, 119446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns.USAGE_TYPE_INT_SHORT_TEXT); 119546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sDataUsageTypeMap = Collections.unmodifiableMap(tmpTypeMap); 119619a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 119719a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 1198d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static class DirectoryInfo { 1199d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String authority; 1200d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountName; 1201d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String accountType; 1202d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 1203d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 1204d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 1205d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Cached information about contact directories. 1206d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 12074458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private HashMap<String, DirectoryInfo> mDirectoryCache = new HashMap<String, DirectoryInfo>(); 12084458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private boolean mDirectoryCacheValid = false; 1209d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 12103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 121143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * An entry in group id cache. It maps the combination of (account type, account name, data set, 1212ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * and source id) to group row id. 1213ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 1214e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov public static class GroupIdCacheEntry { 1215ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType; 1216ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName; 121743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String dataSet; 1218ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String sourceId; 1219ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov long groupId; 1220ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 1221a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1222e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // We don't need a soft cache for groups - the assumption is that there will only 1223e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // be a small number of contact groups. The cache is keyed off source id. The value 1224e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov // is a list of groups with this group id. 1225e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 1226e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov 122724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro /** 1228f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Maximum dimension (height or width) of display photos. Larger images will be scaled 1229f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * to fit. 1230f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 1231f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private int mMaxDisplayPhotoDim; 1232f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1233f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 1234f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Maximum dimension (height or width) of photo thumbnails. 1235f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 1236f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private int mMaxThumbnailPhotoDim; 1237f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 12385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 12395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Sub-provider for handling profile requests against the profile database. 12405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 12415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ProfileProvider mProfileProvider; 1242f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 12434097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1244f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1245315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1246622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1247622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 124872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov private ContactDirectoryManager mContactDirectoryManager; 12495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 12515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * The active (thread-local) database. This will be switched between a contacts-specific 12525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * database and a profile-specific database, depending on what the current operation is 12535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * targeted to. 12545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 12555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<SQLiteDatabase> mActiveDb = new ThreadLocal<SQLiteDatabase>(); 12565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // This variable keeps track of whether the current operation is intended for the profile DB. 12585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<Boolean> mInProfileMode = new ThreadLocal<Boolean>(); 12595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Whether we're currently in the process of applying a batch of operations. 12615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<Boolean> mApplyingBatch = new ThreadLocal<Boolean>(); 12625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Separate data row handler instances for contact data and profile data. 12645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private HashMap<String, DataRowHandler> mDataRowHandlers; 12655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private HashMap<String, DataRowHandler> mProfileDataRowHandlers; 12665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Depending on whether the action being performed is for the profile, we will use one of two 12685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // database helper instances. 12695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<ContactsDatabaseHelper> mDbHelper = 12705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ThreadLocal<ContactsDatabaseHelper>(); 12715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ContactsDatabaseHelper mContactsHelper; 12725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ProfileDatabaseHelper mProfileHelper; 12735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Depending on whether the action being performed is for the profile or not, we will use one of 12755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // two aggregator instances. 12765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<ContactAggregator> mAggregator = new ThreadLocal<ContactAggregator>(); 1277622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 12785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private ContactAggregator mProfileAggregator; 12795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Depending on whether the action being performed is for the profile or not, we will use one of 12815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // two photo store instances (with their files stored in separate subdirectories). 12825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<PhotoStore> mPhotoStore = new ThreadLocal<PhotoStore>(); 12835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private PhotoStore mContactsPhotoStore; 12845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private PhotoStore mProfilePhotoStore; 12855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // The active transaction context will switch depending on the operation being performed. 12875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Both transaction contexts will be cleared out when a batch transaction is started, and 12885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // each will be processed separately when a batch transaction completes. 12895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private TransactionContext mContactTransactionContext = new TransactionContext(false); 12905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private TransactionContext mProfileTransactionContext = new TransactionContext(true); 12915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<TransactionContext> mTransactionContext = 12925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ThreadLocal<TransactionContext>(); 12935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 12945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // This database reference will only be referenced when a batch operation is in progress 12955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // that includes profile DB operations. It is used to create and handle a separate transaction 12965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // around that batch. Outside of such a batch operation, this will be null. 12975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<SQLiteDatabase> mProfileDbForBatch = 12985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new ThreadLocal<SQLiteDatabase>(); 12995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 13005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // This flag is set during a batch operation that involves the profile DB to indicate that 13015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // errors occurred during processing of one of the profile operations. 13025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private final ThreadLocal<Boolean> mProfileErrorsInBatch = new ThreadLocal<Boolean>(); 13035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 1304f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1305a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1306d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov private CommonNicknameCache mCommonNicknameCache; 1307f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov private SearchIndexManager mSearchIndexManager; 1308a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 130920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 131073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov private HashMap<String, Boolean> mAccountWritability = Maps.newHashMap(); 131120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 131209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private int mProviderStatus = ProviderStatus.STATUS_NORMAL; 13133826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private boolean mProviderStatusUpdateNeeded; 131409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private long mEstimatedStorageRequirement = 0; 131515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private volatile CountDownLatch mReadAccessLatch; 131615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private volatile CountDownLatch mWriteAccessLatch; 131715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private boolean mAccountUpdateListenerRegistered; 1318bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private boolean mOkToOpenAccess = true; 131973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 13201a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 13211a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 132281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 132381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 13244cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao private Locale mCurrentLocale; 13253826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private int mContactsAccountCount; 1326d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 1327bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private HandlerThread mBackgroundThread; 1328bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private Handler mBackgroundHandler; 1329bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1330f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private long mLastPhotoCleanup = 0; 1331f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 13324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 13334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1334663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) { 1335663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki Log.d(Constants.PERFORMANCE_TAG, "ContactsProvider2.onCreate start"); 1336663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } 1337de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 1338ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov try { 1339ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return initialize(); 1340ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } catch (RuntimeException e) { 1341ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov Log.e(TAG, "Cannot start provider", e); 1342ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return false; 1343663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } finally { 1344663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) { 1345663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki Log.d(Constants.PERFORMANCE_TAG, "ContactsProvider2.onCreate finish"); 1346663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } 1347ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 1348ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 134935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1350ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov private boolean initialize() { 135115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov StrictMode.setThreadPolicy( 135215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()); 135315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 13543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Resources resources = getContext().getResources(); 1355f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mMaxDisplayPhotoDim = resources.getInteger( 1356f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro R.integer.config_max_display_photo_dim); 1357f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mMaxThumbnailPhotoDim = resources.getInteger( 1358f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro R.integer.config_max_thumbnail_photo_dim); 13593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 13605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper = (ContactsDatabaseHelper) getDatabaseHelper(); 13615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.set(mContactsHelper); 136272e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov mContactDirectoryManager = new ContactDirectoryManager(this); 1363a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 136465ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov 1365bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // The provider is closed for business until fully initialized 136615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch = new CountDownLatch(1); 136715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch = new CountDownLatch(1); 136872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 1369bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundThread = new HandlerThread("ContactsProviderWorker", 1370bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov Process.THREAD_PRIORITY_BACKGROUND); 1371bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundThread.start(); 1372bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler = new Handler(mBackgroundThread.getLooper()) { 1373bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 1374bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void handleMessage(Message msg) { 1375bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov performBackgroundTask(msg.what, msg.obj); 1376bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1377bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov }; 13782a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov 13795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Set up the sub-provider for handling profiles. 13805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileProvider = getProfileProvider(); 13815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ProviderInfo profileInfo = new ProviderInfo(); 13825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileInfo.readPermission = "android.permission.READ_PROFILE"; 13835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileInfo.writePermission = "android.permission.WRITE_PROFILE"; 13845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileProvider.attachInfo(getContext(), profileInfo); 13855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper = (ProfileDatabaseHelper) mProfileProvider.getDatabaseHelper(); 13865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 138715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_INITIALIZE); 1388bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS); 1389bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS); 1390bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_LOCALE); 1391bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM); 139205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_SEARCH_INDEX); 1393bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_PROVIDER_STATUS); 139415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_OPEN_WRITE_ACCESS); 1395f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS); 13963826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 139749d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov return true; 13984f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 13994f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1400767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov /** 140151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * (Re)allocates all locale-sensitive structures. 140251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 140304b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov private void initForDefaultLocale() { 140415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Context context = getContext(); 14055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mLegacyApiSupport = new LegacyApiSupport(context, mContactsHelper, this, 14065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mGlobalSearchSupport); 14074cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mCurrentLocale = getLocale(); 14085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mNameSplitter = mContactsHelper.createNameSplitter(); 14094cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 14104cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mPostalSplitter = new PostalSplitter(mCurrentLocale); 14115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mCommonNicknameCache = new CommonNicknameCache(mContactsHelper.getReadableDatabase()); 1412cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao ContactLocaleUtils.getIntance().setLocale(mCurrentLocale); 14135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactAggregator = new ContactAggregator(this, mContactsHelper, 141415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov createPhotoPriorityResolver(context), mNameSplitter, mCommonNicknameCache); 14155b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 14165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileAggregator = new ProfileAggregator(this, mProfileHelper, 14175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro createPhotoPriorityResolver(context), mNameSplitter, mCommonNicknameCache); 14185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1419f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov mSearchIndexManager = new SearchIndexManager(this); 14205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 14215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsPhotoStore = new PhotoStore(getContext().getFilesDir(), mContactsHelper); 14225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfilePhotoStore = new PhotoStore(new File(getContext().getFilesDir(), "profile"), 14235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper); 14245b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 1425bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 14265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro initDataRowHandlers(mDataRowHandlers, mContactsHelper, mContactAggregator, 14275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsPhotoStore); 14285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDataRowHandlers = new HashMap<String, DataRowHandler>(); 14295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro initDataRowHandlers(mProfileDataRowHandlers, mProfileHelper, mProfileAggregator, 14305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfilePhotoStore); 14315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 14325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Set initial thread-local state variables for the Contacts DB. 14335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 14345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 1435bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 14365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private void initDataRowHandlers(Map<String, DataRowHandler> handlerMap, 14375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ContactsDatabaseHelper dbHelper, ContactAggregator contactAggregator, 14385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PhotoStore photoStore) { 14395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Context context = getContext(); 14405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Email.CONTENT_ITEM_TYPE, 14415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForEmail(context, dbHelper, contactAggregator)); 14425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Im.CONTENT_ITEM_TYPE, 14435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForIm(context, dbHelper, contactAggregator)); 14445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Organization.CONTENT_ITEM_TYPE, 14455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForOrganization(context, dbHelper, contactAggregator)); 14465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Phone.CONTENT_ITEM_TYPE, 14475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForPhoneNumber(context, dbHelper, contactAggregator)); 14485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Nickname.CONTENT_ITEM_TYPE, 14495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForNickname(context, dbHelper, contactAggregator)); 14505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(StructuredName.CONTENT_ITEM_TYPE, 14515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForStructuredName(context, dbHelper, contactAggregator, 1452bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mNameSplitter, mNameLookupBuilder)); 14535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(StructuredPostal.CONTENT_ITEM_TYPE, 14545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForStructuredPostal(context, dbHelper, contactAggregator, 1455bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mPostalSplitter)); 14565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(GroupMembership.CONTENT_ITEM_TYPE, 14575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForGroupMembership(context, dbHelper, contactAggregator, 1458bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mGroupIdCache)); 14595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Photo.CONTENT_ITEM_TYPE, 14605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForPhoto(context, dbHelper, contactAggregator, photoStore)); 14615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handlerMap.put(Note.CONTENT_ITEM_TYPE, 14625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new DataRowHandlerForNote(context, dbHelper, contactAggregator)); 1463bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1464bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1465bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /** 1466bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Visible for testing. 1467bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov */ 1468bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /* package */ PhotoPriorityResolver createPhotoPriorityResolver(Context context) { 1469bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return new PhotoPriorityResolver(context); 1470bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1471bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1472bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void scheduleBackgroundTask(int task) { 1473bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler.sendEmptyMessage(task); 1474bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1475bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1476bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void scheduleBackgroundTask(int task, Object arg) { 1477bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mBackgroundHandler.sendMessage(mBackgroundHandler.obtainMessage(task, arg)); 1478bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1479bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1480bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void performBackgroundTask(int task, Object arg) { 1481bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov switch (task) { 148215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case BACKGROUND_TASK_INITIALIZE: { 148315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov initForDefaultLocale(); 148415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch.countDown(); 148515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mReadAccessLatch = null; 148615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov break; 148715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 148815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 148915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case BACKGROUND_TASK_OPEN_WRITE_ACCESS: { 1490bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (mOkToOpenAccess) { 149115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch.countDown(); 149215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mWriteAccessLatch = null; 1493bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1494bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1495bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1496bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1497bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS: { 1498bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1499bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov importLegacyContactsInBackground(); 1500bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1501bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1502bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1503bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1504bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_ACCOUNTS: { 150515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Context context = getContext(); 150615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (!mAccountUpdateListenerRegistered) { 150715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov AccountManager.get(context).addOnAccountsUpdatedListener(this, null, false); 150815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mAccountUpdateListenerRegistered = true; 150915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 151015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 15115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Update the accounts for both the contacts and profile DBs. 151215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Account[] accounts = AccountManager.get(context).getAccounts(); 15135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 1514bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov boolean accountsChanged = updateAccountsInBackground(accounts); 15155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 15165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro accountsChanged |= updateAccountsInBackground(accounts); 15175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 1518bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateContactsAccountCount(accounts); 1519bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateDirectoriesInBackground(accountsChanged); 1520bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1521bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1522bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1523bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_LOCALE: { 1524bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateLocaleInBackground(); 1525bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1526bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1527bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1528fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov case BACKGROUND_TASK_CHANGE_LOCALE: { 1529fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov changeLocaleInBackground(); 1530fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov break; 1531fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1532fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1533bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPGRADE_AGGREGATION_ALGORITHM: { 1534bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (isAggregationUpgradeNeeded()) { 1535bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov upgradeAggregationAlgorithmInBackground(); 1536bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1537bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1538bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1539bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 154005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_SEARCH_INDEX: { 154105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov updateSearchIndexInBackground(); 154205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov break; 154305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 154405e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 1545bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_PROVIDER_STATUS: { 1546bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov updateProviderStatus(); 1547bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1548bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1549bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1550bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case BACKGROUND_TASK_UPDATE_DIRECTORIES: { 1551bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (arg != null) { 1552bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.onPackageChanged((String) arg); 1553bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1554bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov break; 1555bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1556f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1557f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case BACKGROUND_TASK_CLEANUP_PHOTOS: { 1558f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Check rate limit. 1559f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long now = System.currentTimeMillis(); 1560f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (now - mLastPhotoCleanup > PHOTO_CLEANUP_RATE_LIMIT) { 1561f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mLastPhotoCleanup = now; 15625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 15635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Clean up photo stores for both contacts and profiles. 15645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 15655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro cleanupPhotoStore(); 15665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 1567f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro cleanupPhotoStore(); 1568f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro break; 1569f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1570f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1571bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 15724cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 15734cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao 157453fac8f99f3884c372c907a76766d27fa9e1d95fDmitri Plotnikov public void onLocaleChanged() { 15753826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL 15763826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov && mProviderStatus != ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) { 15774f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov return; 15784f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov } 15794f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov 1580fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_CHANGE_LOCALE); 15814cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 158251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 158351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov /** 158451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * Verifies that the contacts database is properly configured for the current locale. 158551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * If not, changes the database locale to the current locale using an asynchronous task. 158651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * This needs to be done asynchronously because the process involves rebuilding 158751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * large data structures (name lookup, sort keys), which can take minutes on 158851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * a large set of contacts. 158951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 1590bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void updateLocaleInBackground() { 1591f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 1592f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // The process is already running - postpone the change 1593f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov if (mProviderStatus == ProviderStatus.STATUS_CHANGING_LOCALE) { 1594f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov return; 1595f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov } 1596f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 159751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 159851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final String providerLocale = prefs.getString(PREF_LOCALE, null); 159951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final Locale currentLocale = mCurrentLocale; 160051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov if (currentLocale.toString().equals(providerLocale)) { 160151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return; 160251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 160351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 160451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov int providerStatus = mProviderStatus; 160551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_CHANGING_LOCALE); 16065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setLocale(this, currentLocale); 16075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper.setLocale(this, currentLocale); 1608bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, currentLocale.toString()).apply(); 1609bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov setProviderStatus(providerStatus); 1610bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 161151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 1612fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov /** 1613fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov * Reinitializes the provider for a new locale. 1614fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov */ 1615fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov private void changeLocaleInBackground() { 1616fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // Re-initializing the provider without stopping it. 1617fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // Locking the database will prevent inserts/updates/deletes from 1618fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // running at the same time, but queries may still be running 1619fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov // on other threads. Those queries may return inconsistent results. 16205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mContactsHelper.getWritableDatabase(); 16215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase profileDb = mProfileHelper.getWritableDatabase(); 1622fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.beginTransaction(); 16235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.beginTransaction(); 1624fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov try { 1625fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov initForDefaultLocale(); 1626fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.setTransactionSuccessful(); 16275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.setTransactionSuccessful(); 1628fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } finally { 1629fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov db.endTransaction(); 16305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.endTransaction(); 1631fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1632fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1633fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov updateLocaleInBackground(); 1634fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1635fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 163605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov protected void updateSearchIndexInBackground() { 163705e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov mSearchIndexManager.updateIndex(); 163805e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 163905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 1640bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void updateDirectoriesInBackground(boolean rescan) { 1641bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.scanAllPackages(rescan); 164251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 164351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 16443826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private void updateProviderStatus() { 16453826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != ProviderStatus.STATUS_NORMAL 16463826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov && mProviderStatus != ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) { 16473826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return; 16483826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 16493826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 16503e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson // No accounts/no contacts status is true if there are no account and 16515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // there are no contacts or one profile contact 16523e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson if (mContactsAccountCount == 0) { 16535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactsNum = DatabaseUtils.queryNumEntries(mContactsHelper.getReadableDatabase(), 16543e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson Tables.CONTACTS, null); 16555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long profileNum = DatabaseUtils.queryNumEntries(mProfileHelper.getReadableDatabase(), 16565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Tables.CONTACTS, null); 16575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 16585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // TODO: Different status if there is a profile but no contacts? 16595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (contactsNum == 0 && profileNum <= 1) { 16603e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson setProviderStatus(ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS); 16613e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson } else { 16623e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson setProviderStatus(ProviderStatus.STATUS_NORMAL); 16633e6cd1fbafd09bf9b6ec35a19a55b48a271727dfIsaac Katzenelson } 16643826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } else { 16653826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 16663826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 16673826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 16683826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 166931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 1670f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro protected void cleanupPhotoStore() { 16715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mDbHelper.get().getWritableDatabase(); 16726802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 16736802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Assemble the set of photo store file IDs that are in use, and send those to the photo 1674f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // store. Any photos that aren't in that set will be deleted, and any photos that no 1675f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // longer exist in the photo store will be returned for us to clear out in the DB. 16766802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Cursor c = db.query(Views.DATA, new String[]{Data._ID, Photo.PHOTO_FILE_ID}, 1677f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Data.MIMETYPE + "=" + Photo.MIMETYPE + " AND " 1678f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro + Photo.PHOTO_FILE_ID + " IS NOT NULL", null, null, null, null); 16796802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Set<Long> usedPhotoFileIds = Sets.newHashSet(); 16806802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Map<Long, Long> photoFileIdToDataId = Maps.newHashMap(); 1681f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 1682f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro while (c.moveToNext()) { 16836802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long dataId = c.getLong(0); 16846802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long photoFileId = c.getLong(1); 16856802030a777c0c3ba1dc029c534cca4784260632Dave Santoro usedPhotoFileIds.add(photoFileId); 16866802030a777c0c3ba1dc029c534cca4784260632Dave Santoro photoFileIdToDataId.put(photoFileId, dataId); 16876802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 16886802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } finally { 16896802030a777c0c3ba1dc029c534cca4784260632Dave Santoro c.close(); 16906802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 16916802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 16926802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Also query for all social stream item photos. 1693c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro c = db.query(Tables.STREAM_ITEM_PHOTOS + " JOIN " + Tables.STREAM_ITEMS 1694c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro + " ON " + StreamItemPhotos.STREAM_ITEM_ID + "=" + StreamItemsColumns.CONCRETE_ID 1695c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro + " JOIN " + Tables.RAW_CONTACTS 1696c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro + " ON " + StreamItems.RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID, 16976802030a777c0c3ba1dc029c534cca4784260632Dave Santoro new String[]{ 1698c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro StreamItemPhotosColumns.CONCRETE_ID, 1699c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID, 1700c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro StreamItemPhotos.PHOTO_FILE_ID, 1701c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro RawContacts.ACCOUNT_TYPE, 1702c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro RawContacts.ACCOUNT_NAME 17036802030a777c0c3ba1dc029c534cca4784260632Dave Santoro }, 17046802030a777c0c3ba1dc029c534cca4784260632Dave Santoro null, null, null, null, null); 17056802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Map<Long, Long> photoFileIdToStreamItemPhotoId = Maps.newHashMap(); 17066802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Map<Long, Long> streamItemPhotoIdToStreamItemId = Maps.newHashMap(); 1707c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro Map<Long, Account> streamItemPhotoIdToAccount = Maps.newHashMap(); 17086802030a777c0c3ba1dc029c534cca4784260632Dave Santoro try { 17096802030a777c0c3ba1dc029c534cca4784260632Dave Santoro while (c.moveToNext()) { 17106802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemPhotoId = c.getLong(0); 17116802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemId = c.getLong(1); 17126802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long photoFileId = c.getLong(2); 1713c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro String accountType = c.getString(3); 1714c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro String accountName = c.getString(4); 17156802030a777c0c3ba1dc029c534cca4784260632Dave Santoro usedPhotoFileIds.add(photoFileId); 17166802030a777c0c3ba1dc029c534cca4784260632Dave Santoro photoFileIdToStreamItemPhotoId.put(photoFileId, streamItemPhotoId); 17176802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemPhotoIdToStreamItemId.put(streamItemPhotoId, streamItemId); 1718c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro Account account = new Account(accountName, accountType); 1719c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro streamItemPhotoIdToAccount.put(photoFileId, account); 1720f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1721f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 1722f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 1723f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1724f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1725f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Run the photo store cleanup. 17265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> missingPhotoIds = mPhotoStore.get().cleanup(usedPhotoFileIds); 1727f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1728f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // If any of the keys we're using no longer exist, clean them up. 17296802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (!missingPhotoIds.isEmpty()) { 1730f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ArrayList<ContentProviderOperation> ops = Lists.newArrayList(); 17316802030a777c0c3ba1dc029c534cca4784260632Dave Santoro for (long missingPhotoId : missingPhotoIds) { 17326802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoFileIdToDataId.containsKey(missingPhotoId)) { 17336802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long dataId = photoFileIdToDataId.get(missingPhotoId); 1734f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ContentValues updateValues = new ContentValues(); 1735f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.putNull(Photo.PHOTO_FILE_ID); 1736f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ops.add(ContentProviderOperation.newUpdate( 17376802030a777c0c3ba1dc029c534cca4784260632Dave Santoro ContentUris.withAppendedId(Data.CONTENT_URI, dataId)) 1738f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .withValues(updateValues).build()); 1739f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 17406802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoFileIdToStreamItemPhotoId.containsKey(missingPhotoId)) { 17416802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // For missing photos that were in stream item photos, just delete the stream 17426802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // item photo. 17436802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemPhotoId = photoFileIdToStreamItemPhotoId.get(missingPhotoId); 17446802030a777c0c3ba1dc029c534cca4784260632Dave Santoro long streamItemId = streamItemPhotoIdToStreamItemId.get(streamItemPhotoId); 1745c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro Account account = streamItemPhotoIdToAccount.get(missingPhotoId); 17466802030a777c0c3ba1dc029c534cca4784260632Dave Santoro ops.add(ContentProviderOperation.newDelete( 17476802030a777c0c3ba1dc029c534cca4784260632Dave Santoro StreamItems.CONTENT_URI.buildUpon() 17486802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .appendPath(String.valueOf(streamItemId)) 17496802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .appendPath(StreamItems.StreamItemPhotos.CONTENT_DIRECTORY) 17506802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .appendPath(String.valueOf(streamItemPhotoId)) 1751c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro .appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name) 1752c2714bbd397b09a20da476c89560e1caecdcce58Dave Santoro .appendQueryParameter(RawContacts.ACCOUNT_TYPE, account.type) 17536802030a777c0c3ba1dc029c534cca4784260632Dave Santoro .build()).build()); 17546802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 1755f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1756f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 1757f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro applyBatch(ops); 1758f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } catch (OperationApplicationException oae) { 1759f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Not a fatal problem (and we'll try again on the next cleanup). 1760f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Log.e(TAG, "Failed to clean up outdated photo references", oae); 1761f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1762f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1763f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1764f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1765f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /* Visible for testing */ 1766de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 1767b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 1768b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 176931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 177031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 17715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public ProfileProvider getProfileProvider() { 17725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return new ProfileProvider(this); 17735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 17745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 1775524913c66ce75ca8dec127ac88e3bc2249c246d9Dave Santoro @VisibleForTesting 1776f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /* package */ PhotoStore getPhotoStore() { 17775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mContactsPhotoStore; 1778f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 1779f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 178087614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro /* package */ int getMaxDisplayPhotoDim() { 178187614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro return mMaxDisplayPhotoDim; 178287614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro } 178387614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro 178487614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro /* package */ int getMaxThumbnailPhotoDim() { 178587614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro return mMaxThumbnailPhotoDim; 178687614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro } 178787614d7d293b1519dc1f0f403fd59c8bf4d8a347Dave Santoro 1788013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 1789013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 1790013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1791013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 17925df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov /* package */ NameLookupBuilder getNameLookupBuilder() { 17935df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov return mNameLookupBuilder; 17945df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov } 17955df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov 17965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov /* Visible for testing */ 1797ed78fd6df5e9f3a2d572162e5d374d1f4a625bddDmitri Plotnikov public ContactDirectoryManager getContactDirectoryManagerForTest() { 179872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov return mContactDirectoryManager; 179972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 180072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 180172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov /* Visible for testing */ 18025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov protected Locale getLocale() { 18035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov return Locale.getDefault(); 18045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 18055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 18065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean applyingBatch() { 18075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Boolean applyingBatch = mApplyingBatch.get(); 18085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return applyingBatch != null && applyingBatch; 18095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 18105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 18115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean inProfileMode() { 18125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Boolean profileMode = mInProfileMode.get(); 18135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return profileMode != null && profileMode; 18145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 18155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 18163d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 18175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int version = Integer.parseInt( 18185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.getProperty(PROPERTY_CONTACTS_IMPORTED, "0")); 1819b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return version < PROPERTY_CONTACTS_IMPORT_VERSION; 18203d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18213d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1822568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 1823568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 1824568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1825568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1826568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 1827bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Imports legacy contacts as a background task. 1828568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 1829bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private void importLegacyContactsInBackground() { 1830bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Importing legacy contacts"); 1831bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADING); 1832568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1833bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 18345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setLocale(this, mCurrentLocale); 1835bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, mCurrentLocale.toString()).commit(); 1836568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1837bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 1838bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (importLegacyContacts(importer)) { 1839bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov onLegacyContactImportSuccess(); 1840bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } else { 1841bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov onLegacyContactImportFailure(); 1842bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1843568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1844568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1845bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1846bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Unlocks the provider and declares that the import process is complete. 1847bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1848bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportSuccess() { 1849bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 1850bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)getContext().getSystemService(Context.NOTIFICATION_SERVICE); 1851bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.cancel(LEGACY_IMPORT_FAILED_NOTIFICATION); 1852bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1853b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov // Store a property in the database indicating that the conversion process succeeded 18545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setProperty(PROPERTY_CONTACTS_IMPORTED, 1855b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov String.valueOf(PROPERTY_CONTACTS_IMPORT_VERSION)); 1856bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 1857bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Completed import of legacy contacts"); 1858bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1859bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1860bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 1861bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Announces the provider status and keeps the provider locked. 1862bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 1863bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportFailure() { 1864bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Context context = getContext(); 1865bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 1866bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); 1867bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1868bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // Show a notification 1869bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Notification n = new Notification(android.R.drawable.stat_notify_error, 1870bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_ticker), 1871bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov System.currentTimeMillis()); 1872bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.setLatestEventInfo(context, 1873bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_title), 1874bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_text), 1875bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov PendingIntent.getActivity(context, 0, new Intent(Intents.UI.LIST_DEFAULT), 0)); 1876bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; 1877bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1878bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.notify(LEGACY_IMPORT_FAILED_NOTIFICATION, n); 1879bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1880bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADE_OUT_OF_MEMORY); 1881bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Failed to import legacy contacts"); 1882bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1883bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // Do not let any database changes until this issue is resolved. 1884bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mOkToOpenAccess = false; 18853d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 18863d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 18873d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 1888568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 18890e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 18903d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 18913d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 1892bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (importer.importContacts()) { 1893bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1894bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // TODO aggregate all newly added raw contacts 1895bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mContactAggregator.setEnabled(aggregatorEnabled); 1896bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return true; 1897bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 18983d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 18993d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 19003d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1901bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mEstimatedStorageRequirement = importer.getEstimatedStorageRequirement(); 1902bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return false; 19033d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 19043d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1905a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1906a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1907a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1908a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 19095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.wipeData(); 19105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileHelper.wipeData(); 19115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsPhotoStore.clear(); 19125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfilePhotoStore.clear(); 19133826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatus = ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS; 1914a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1915a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1916568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 191715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov * During intialization, this content provider will 1918568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 1919568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1920568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 1921568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 1922568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 192315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private void waitForAccess(CountDownLatch latch) { 192415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (latch == null) { 192515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return; 192615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 192715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 192815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov while (true) { 192915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov try { 193015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov latch.await(); 193115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return; 193215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } catch (InterruptedException e) { 193315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Thread.currentThread().interrupt(); 1934ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 1935568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1936568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1937568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 19385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 19395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Determines whether the given URI should be directed to the profile 19405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * database rather than the contacts database. This is true under either 19415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * of three conditions: 19425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * 1. The URI itself is specifically for the profile. 19435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * 2. The URI contains ID references that are in the profile ID-space. 19445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * 3. The URI contains lookup key references that match the special profile lookup key. 19455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param uri The URI to examine. 19465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @return Whether to direct the DB operation to the profile database. 19475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 19485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean mapsToProfileDb(Uri uri) { 19495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return sUriMatcher.mapsToProfile(uri); 19505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 19525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 19535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Determines whether the given URI with the given values being inserted 19545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * should be directed to the profile database rather than the contacts 19555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * database. This is true if the URI already maps to the profile DB from 19565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * a call to {@link #mapsToProfileDb} or if the URI matches a URI that 19575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * specifies parent IDs via the ContentValues, and the given ContentValues 19585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * contains an ID in the profile ID-space. 19595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param uri The URI to examine. 19605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param values The values being inserted. 19615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @return Whether to direct the DB insert to the profile database. 19625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 19635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private boolean mapsToProfileDbWithInsertedValues(Uri uri, ContentValues values) { 19645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 19655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return true; 19665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int match = sUriMatcher.match(uri); 19685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (INSERT_URI_ID_VALUE_MAP.containsKey(match)) { 19695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String idField = INSERT_URI_ID_VALUE_MAP.get(match); 19705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (values.containsKey(idField)) { 19715d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long id = values.getAsLong(idField); 19725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (ContactsContract.isProfileId(id)) { 19735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return true; 19745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return false; 19785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 19805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 19815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Switches the provider's thread-local context variables to prepare for performing 19825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * a profile operation. 19835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 19845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private void switchToProfileMode() { 19855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.set(mProfileHelper); 19865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.set(mProfileTransactionContext); 19875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.set(mProfileAggregator); 19885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mPhotoStore.set(mProfilePhotoStore); 19895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mInProfileMode.set(true); 19905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 19915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // If we're in batch mode and don't yet have a database set up for our transaction, 19925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // get one and start a transaction now. 19935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (applyingBatch() && mProfileDbForBatch.get() == null) { 19945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase profileDb = mProfileHelper.getWritableDatabase(); 19955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro profileDb.beginTransactionWithListener(this); 19965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDbForBatch.set(profileDb); 19975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 19995d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 20005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 20015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Switches the provider's thread-local context variables to prepare for performing 20025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * a contacts operation. 20035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 20045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private void switchToContactMode() { 20055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.set(mContactsHelper); 20065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.set(mContactTransactionContext); 20075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.set(mContactAggregator); 20085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mPhotoStore.set(mContactsPhotoStore); 20095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mInProfileMode.set(false); 20105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 20115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // If not in batch mode, clear out the active database - it will be set to the default 20125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // instance from SQLiteContentProvider if necessary. 20135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (!applyingBatch()) { 20145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(null); 20155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 20175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 2018568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2019568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 202015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 20215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDbWithInsertedValues(uri, values)) { 2022072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro if (applyingBatch()) { 2023072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2024072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return mProfileProvider.insert(uri, values); 2025072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } else { 2026072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Start a contacts DB transaction to maintain provider synchronization. 2027072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro SQLiteDatabase contactsDb = mContactsHelper.getWritableDatabase(); 2028072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.beginTransactionWithListener(this); 2029072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro Uri result = null; 2030072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro try { 2031072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Now switch to profile mode and proceed with the insert using its provider. 2032072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2033072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro result = mProfileProvider.insert(uri, values); 2034072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2035072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.setTransactionSuccessful(); 2036072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } finally { 2037072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Finish the contacts transaction, allowing other provider operations to 2038072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // proceed. 2039072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.endTransaction(); 2040072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 2041072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return result; 2042072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 20435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 20445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 20455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return super.insert(uri, values); 20465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 2047568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2048568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2049568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2050568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 205115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (mWriteAccessLatch != null) { 2052bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // We are stuck trying to upgrade contacts db. The only update request 2053bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // allowed in this case is an update of provider status, which will trigger 2054bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // an attempt to upgrade contacts again. 2055bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov int match = sUriMatcher.match(uri); 2056bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (match == PROVIDER_STATUS) { 2057bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Integer newStatus = values.getAsInteger(ProviderStatus.STATUS); 2058bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (newStatus != null && newStatus == ProviderStatus.STATUS_UPGRADING) { 2059bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_IMPORT_LEGACY_CONTACTS); 2060bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 1; 2061bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 2062bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 0; 2063bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2064bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2065bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 206615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 20675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 2068072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro if (applyingBatch()) { 2069072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2070072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return mProfileProvider.update(uri, values, selection, selectionArgs); 2071072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } else { 2072072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Start a contacts DB transaction to maintain provider synchronization. 2073072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro SQLiteDatabase contactsDb = mContactsHelper.getWritableDatabase(); 2074072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.beginTransactionWithListener(this); 2075072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro int result = 0; 2076072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro try { 2077072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Now switch to profile mode and proceed with the update using its provider. 2078072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2079072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro result = mProfileProvider.update(uri, values, selection, selectionArgs); 2080072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2081072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.setTransactionSuccessful(); 2082072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } finally { 2083072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Finish the contacts transaction, allowing other provider operations to 2084072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // proceed. 2085072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.endTransaction(); 2086072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 2087072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return result; 2088072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 20895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 20905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 20915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return super.update(uri, values, selection, selectionArgs); 20925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 2093568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2094568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2095568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2096568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 209715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 20985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 2099072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro if (applyingBatch()) { 2100072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2101072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return mProfileProvider.delete(uri, selection, selectionArgs); 2102072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } else { 2103072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Start a contacts DB transaction to maintain provider synchronization. 2104072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro SQLiteDatabase contactsDb = mContactsHelper.getWritableDatabase(); 2105072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.beginTransactionWithListener(this); 2106072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro int result = 0; 2107072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro try { 2108072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Now switch to profile mode and proceed with the delete using its provider. 2109072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro switchToProfileMode(); 2110072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro result = mProfileProvider.delete(uri, selection, selectionArgs); 2111072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2112072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.setTransactionSuccessful(); 2113072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } finally { 2114072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Finish the contacts transaction, allowing other provider operations to 2115072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // proceed. 2116072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro contactsDb.endTransaction(); 2117072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 2118072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro return result; 2119072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro } 21205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 21215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 21225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return super.delete(uri, selection, selectionArgs); 21235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 21265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /** 21275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * Replaces the current (thread-local) database to use for the operation with the given one. 21285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro * @param db The database to use. 21295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro */ 21305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro /* package */ void substituteDb(SQLiteDatabase db) { 21315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(db); 2132568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2133568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2134568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2135568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 2136568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 213715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mWriteAccessLatch); 21385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ContentProviderResult[] results = null; 21395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro try { 21405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro results = super.applyBatch(operations); 21415d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } finally { 21425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mProfileDbForBatch.get() != null) { 21435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // A profile operation was involved, so clean up its transaction. 21445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro boolean profileErrors = mProfileErrorsInBatch.get() != null 21455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro && mProfileErrorsInBatch.get(); 21465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (!profileErrors) { 21475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDbForBatch.get().setTransactionSuccessful(); 21485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDbForBatch.get().endTransaction(); 21505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDbForBatch.set(null); 21515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileErrorsInBatch.set(false); 21525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 21545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return results; 2155568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2156568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 21574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 21587b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov public int bulkInsert(Uri uri, ContentValues[] values) { 21597b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov waitForAccess(mWriteAccessLatch); 2160720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro 2161720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro // Note: This duplicates much of the logic in the superclass, but handles toggling 2162720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro // into profile mode if necessary. 2163720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro int numValues = values.length; 2164720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro boolean notifyChange = false; 2165720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro SQLiteDatabase profileDb = null; 2166072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2167072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Always get a contacts DB and start a transaction on it, to maintain provider 2168072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // synchronization. 21698d55bbc171bea632e960e0e5a88557cef5e66d92Dave Santoro mDb = mContactsHelper.getWritableDatabase(); 21708d55bbc171bea632e960e0e5a88557cef5e66d92Dave Santoro mDb.beginTransactionWithListener(this); 2171720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro try { 2172720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro for (int i = 0; i < numValues; i++) { 2173720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro Uri result; 2174720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (mapsToProfileDbWithInsertedValues(uri, values[i])) { 2175720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro switchToProfileMode(); 2176072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro 2177072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // Initialize the profile DB and start a profile transaction if we haven't 2178072079319b9bd2998b06a2cab0e9b4af6eb05c33Dave Santoro // already done so. 2179720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (profileDb == null) { 2180720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro profileDb = mProfileHelper.getWritableDatabase(); 2181720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro profileDb.beginTransactionWithListener(this); 2182720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2183720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro result = mProfileProvider.insertInTransaction(uri, values[i]); 2184720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } else { 2185720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro switchToContactMode(); 2186720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro result = insertInTransaction(uri, values[i]); 2187720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2188720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (result != null) { 2189720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro notifyChange = true; 2190720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2191720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro boolean savedNotifyChange = notifyChange; 2192720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro mActiveDb.get().yieldIfContendedSafely(); 2193720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro notifyChange = savedNotifyChange; 2194720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 21958d55bbc171bea632e960e0e5a88557cef5e66d92Dave Santoro mDb.setTransactionSuccessful(); 2196720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (profileDb != null) { 2197720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro profileDb.setTransactionSuccessful(); 2198720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2199720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } finally { 22008d55bbc171bea632e960e0e5a88557cef5e66d92Dave Santoro mDb.endTransaction(); 2201720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (profileDb != null) { 2202720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro profileDb.endTransaction(); 2203720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2204720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2205720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro 2206720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro if (notifyChange) { 2207720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro notifyChange(); 2208720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro } 2209720277eff4ffa6344ce2efc1fc39f9ced8af0b6bDave Santoro return numValues; 22107b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov } 22117b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov 22127b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov @Override 2213285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 2214bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2215b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 2216b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2217285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 22185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (inProfileMode()) { 22195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileAggregator.clearPendingAggregations(); 22205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileTransactionContext.clear(); 22215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 22225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactAggregator.clearPendingAggregations(); 22235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactTransactionContext.clear(); 22245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 2225b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2226b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2227285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2228285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2229285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 22301129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 2231bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2232b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 2233b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2234285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 2235b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 22365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().aggregateInTransaction(mTransactionContext.get(), mActiveDb.get()); 22371a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 22381a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 22395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().updateAllVisible(); 22401a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 22413826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 2242bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 2243bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov 22443826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatusUpdateNeeded) { 22453826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateProviderStatus(); 22463826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = false; 22473826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 2248b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2249b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2250bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov private void updateSearchIndexInTransaction() { 22515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> staleContacts = mTransactionContext.get().getStaleSearchIndexContactIds(); 22525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> staleRawContacts = mTransactionContext.get().getStaleSearchIndexRawContactIds(); 2253bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov if (!staleContacts.isEmpty() || !staleRawContacts.isEmpty()) { 2254bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov mSearchIndexManager.updateIndexForRawContacts(staleContacts, staleRawContacts); 22555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().clearSearchIndexUpdates(); 2256bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov } 2257bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov } 2258bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov 2259b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 2260bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2261b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 2262b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 22631129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 22645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro for (long rawContactId : mTransactionContext.get().getInsertedRawContactIds()) { 22655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().updateRawContactDisplayName(mActiveDb.get(), rawContactId); 22665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().onRawContactInsert(mTransactionContext.get(), mActiveDb.get(), 22675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro rawContactId); 226824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 226924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 22705d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> dirtyRawContacts = mTransactionContext.get().getDirtyRawContactIds(); 2271d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (!dirtyRawContacts.isEmpty()) { 2272a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2273a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 2274d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov appendIds(mSb, dirtyRawContacts); 2275a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 22765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(mSb.toString()); 2277a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 2278a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 22795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Set<Long> updatedRawContacts = mTransactionContext.get().getUpdatedRawContactIds(); 2280d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov if (!updatedRawContacts.isEmpty()) { 2281a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2282a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 2283d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov appendIds(mSb, updatedRawContacts); 2284a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 22855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(mSb.toString()); 2286b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2287b5a4add17815167d20a90645779df34cdf45280dFred Quintana 22885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Update sync states. 22895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro for (Map.Entry<Long, Object> entry : mTransactionContext.get().getUpdatedSyncStates()) { 2290b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 22915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().getSyncState().update(mActiveDb.get(), id, entry.getValue()) <= 0) { 22929d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana throw new IllegalStateException( 22939d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana "unable to update sync state, does it still exist?"); 22949d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana } 2295b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2296b5a4add17815167d20a90645779df34cdf45280dFred Quintana 22975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().clear(); 2298b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2299b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2300a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** 2301a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * Appends comma separated ids. 2302a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * @param ids Should not be empty 2303a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov */ 2304d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov private void appendIds(StringBuilder sb, Set<Long> ids) { 2305b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 2306a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(id).append(','); 2307b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2308a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2309a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 2310285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2311285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2312285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2313cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 231481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 231581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 231681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 231781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 231881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 231981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 232081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 2321cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 2322568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 232351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void setProviderStatus(int status) { 23243826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (mProviderStatus != status) { 23253826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatus = status; 23263826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov getContext().getContentResolver().notifyChange(ProviderStatus.CONTENT_URI, null, false); 23273826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 232851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 232951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 2330f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov public DataRowHandler getDataRowHandler(final String mimeType) { 23315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (inProfileMode()) { 23325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return getDataRowHandlerForProfile(mimeType); 23335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 23353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 23366d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov handler = new DataRowHandlerForCustomMimetype( 23375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro getContext(), mContactsHelper, mContactAggregator, mimeType); 23383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 23393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 23403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 23413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 23423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 23435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public DataRowHandler getDataRowHandlerForProfile(final String mimeType) { 23445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro DataRowHandler handler = mProfileDataRowHandlers.get(mimeType); 23455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (handler == null) { 23465d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro handler = new DataRowHandlerForCustomMimetype( 23475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro getContext(), mProfileHelper, mProfileAggregator, mimeType); 23485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mProfileDataRowHandlers.put(mimeType, handler); 23495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return handler; 23515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 23534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2354de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 2355bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 23561129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Log.v(TAG, "insertInTransaction: " + uri + " " + values); 2357b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2358f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 23595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 23605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 23615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 23625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 23635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 2364f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2365f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2366f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2367a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 2368a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 236935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2370a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 237135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 23725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 23735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = mDbHelper.get().getSyncState().insert(mActiveDb.get(), values); 237435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 237535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2376d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2377d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 23786bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 23796bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 23806bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 238124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: { 238224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro throw new UnsupportedOperationException( 238324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro "The profile contact is created automatically"); 238424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 238524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 23865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 23875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = insertRawContact(uri, values, callerIsSyncAdapter); 2388f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2389a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2390a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2391a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 23925ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 23935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 2394f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2395f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2396a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2397a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2398a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 23993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case RAW_CONTACTS_ID_STREAM_ITEMS: { 24003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.put(StreamItems.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 24013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItem(uri, values); 24023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 240624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS: { 24075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = insertRawContact(uri, values, callerIsSyncAdapter); 240824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro mSyncToNetwork |= !callerIsSyncAdapter; 240924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 241024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 241124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 24120c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case DATA: 24130c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case PROFILE_DATA: { 2414f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2415f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2416a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2417a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2418a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2419ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2420f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertGroup(uri, values, callerIsSyncAdapter); 2421f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2422ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2423ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2424ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2425eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 24265aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 242743880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2428eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2429eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2430eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 24315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 24325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 243382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 24341f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 24351f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 24361f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 24373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 24383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItem(uri, values); 24393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 24433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 24443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItemPhoto(uri, values); 24453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 24493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 24503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.put(StreamItemPhotos.STREAM_ITEM_ID, uri.getPathSegments().get(1)); 24513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = insertStreamItemPhoto(uri, values); 24523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 24533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 24543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 24553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 2456a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 245781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2458f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 2459a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2460a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 24617e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 24627e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 24637e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 24647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2465de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 2466a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2467a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2468a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2469e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * If account is non-null then store it in the values. If the account is 2470e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * already specified in the values then it must be consistent with the 2471e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * account, if it is non-null. 2472e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * 2473e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param uri Current {@link Uri} being operated on. 2474e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param values {@link ContentValues} to read and possibly update. 2475e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when only one of 2476e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_NAME} or 2477e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_TYPE} is specified, leaving the 2478e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * other undefined. 2479e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when {@link RawContacts#ACCOUNT_NAME} 2480e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * and {@link RawContacts#ACCOUNT_TYPE} are inconsistent between 2481e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * the given {@link Uri} and {@link ContentValues}. 24827e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 2483e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey private Account resolveAccount(Uri uri, ContentValues values) throws IllegalArgumentException { 2484f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 2485f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 2486e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 2487f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2488f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 2489f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2490e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialValues = TextUtils.isEmpty(valueAccountName) 2491e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ^ TextUtils.isEmpty(valueAccountType); 2492e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2493e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri || partialValues) { 2494e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 24955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 2496fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 2497e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2498e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2499e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 2500e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 2501e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validUri = !TextUtils.isEmpty(accountName); 2502e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validValues = !TextUtils.isEmpty(valueAccountName); 2503e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2504e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validValues && validUri) { 2505e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Check that accounts match when both present 2506e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean accountMatch = TextUtils.equals(accountName, valueAccountName) 2507e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey && TextUtils.equals(accountType, valueAccountType); 2508e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (!accountMatch) { 25095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 2510fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "When both specified, ACCOUNT_NAME and ACCOUNT_TYPE must match", uri)); 2511e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2512e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validUri) { 2513e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Fill values from Uri when not present 2514f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, accountName); 2515f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, accountType); 2516e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validValues) { 2517f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountName = valueAccountName; 2518f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountType = valueAccountType; 2519e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else { 2520e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return null; 2521f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2522f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2523e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Use cached Account object when matches, otherwise create 2524f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mAccount == null 2525f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.name.equals(accountName) 2526f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.type.equals(accountType)) { 2527f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mAccount = new Account(accountName, accountType); 2528035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2529f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2530e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return mAccount; 25317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 253443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * Resolves the account and builds an {@link AccountWithDataSet} based on the data set specified 253543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * in the URI or values (if any). 253643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * @param uri Current {@link Uri} being operated on. 253743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * @param values {@link ContentValues} to read and possibly update. 253843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro */ 253943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro private AccountWithDataSet resolveAccountWithDataSet(Uri uri, ContentValues values) { 25403593682b8d9213fde576a0cff54458ad50563980Dave Santoro final Account account = resolveAccount(uri, values); 254143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro AccountWithDataSet accountWithDataSet = null; 254243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (account != null) { 254343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String dataSet = getQueryParameter(uri, RawContacts.DATA_SET); 254443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (dataSet == null) { 25453593682b8d9213fde576a0cff54458ad50563980Dave Santoro dataSet = values.getAsString(RawContacts.DATA_SET); 2546a71dc460ca951c7aca591f3f470c160cde70a1e3Dave Santoro } else { 25473593682b8d9213fde576a0cff54458ad50563980Dave Santoro values.put(RawContacts.DATA_SET, dataSet); 254843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 254943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet = new AccountWithDataSet(account.name, account.type, dataSet); 255043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 255143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro return accountWithDataSet; 255243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 255343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 255443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro /** 2555d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 25566bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 25576bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 25586bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 25596bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2560d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2561de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 25626bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 25636bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 25646bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 256524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro * Inserts an item in the raw contacts table 2566a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2567f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param uri the values for the new row 2568f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param values the account this contact should be associated with. may be null. 2569dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana * @param callerIsSyncAdapter 2570a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2571a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 25725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private long insertRawContact(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 2573f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2574f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2575f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2576f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 257743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro AccountWithDataSet accountWithDataSet = resolveAccountWithDataSet(uri, mValues); 25787e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25793d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 25803d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 2581f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 25823d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 25833d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 25845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long rawContactId = mActiveDb.get().insert(Tables.RAW_CONTACTS, 25855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro RawContacts.CONTACT_ID, mValues); 2586f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = RawContacts.AGGREGATION_MODE_DEFAULT; 25875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mValues.containsKey(RawContacts.AGGREGATION_MODE)) { 2588f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov aggregationMode = mValues.getAsInteger(RawContacts.AGGREGATION_MODE); 2589f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 25905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markNewForAggregation(rawContactId, aggregationMode); 2591285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 25925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Trigger creation of a Contact based on this RawContact at the end of transaction 25935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().rawContactInserted(rawContactId, accountWithDataSet); 2594f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2595dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 2596dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 2597dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long starred = values.getAsLong(RawContacts.STARRED); 2598dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (starred != null && starred != 0) { 2599dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred != 0); 2600dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2601dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2602dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 26033826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 2604023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2605a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2606a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2607dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void addAutoAddMembership(long rawContactId) { 2608dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID, 2609dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 2610dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 2611dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 2612dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2613dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2614dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2615dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private Long findGroupByRawContactId(String selection, long rawContactId) { 26165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.GROUPS + "," + Tables.RAW_CONTACTS, 26175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROJECTION_GROUP_ID, selection, 2618dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}, 2619dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana null /* groupBy */, null /* having */, null /* orderBy */); 2620dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 2621dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (c.moveToNext()) { 2622dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return c.getLong(0); 2623dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2624dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return null; 2625dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 2626dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana c.close(); 2627dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2628dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2629dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2630dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void updateFavoritesMembership(long rawContactId, boolean isStarred) { 2631dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID, 2632dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 2633dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 2634dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (isStarred) { 2635dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 2636dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 2637dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana deleteDataGroupMembership(rawContactId, groupId); 2638dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2639dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2640dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2641dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2642dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void insertDataGroupMembership(long rawContactId, long groupId) { 2643dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ContentValues groupMembershipValues = new ContentValues(); 2644dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.GROUP_ROW_ID, groupId); 2645dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.RAW_CONTACT_ID, rawContactId); 2646dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(DataColumns.MIMETYPE_ID, 26475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 26485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().insert(Tables.DATA, null, groupMembershipValues); 2649dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2650dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2651dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void deleteDataGroupMembership(long rawContactId, long groupId) { 2652dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final String[] selectionArgs = { 26535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Long.toString(mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)), 2654dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(groupId), 2655dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(rawContactId)}; 26565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.DATA, SELECTION_GROUPMEMBERSHIP_DATA, selectionArgs); 2657dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2658dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2659a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2660a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2661a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2662a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2663a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2664a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2665f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2666a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2667de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2668de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 266967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2670de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 267120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2672de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2673de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2674de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 26755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(DataColumns.PACKAGE_ID, mDbHelper.get().getPackageId(packageName)); 2676de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2677de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2678508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2679de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2680de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2681de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2682de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2683de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 26844097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 26855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.get().getMimeTypeId(mimeType)); 2686de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2687a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2688a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 26895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = rowHandler.insert(mActiveDb.get(), mTransactionContext.get(), rawContactId, mValues); 2690f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 26915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().markRawContactDirty(rawContactId); 2692a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 26935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().rawContactUpdated(rawContactId); 2694a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 26954f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 26964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 26973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 26983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Inserts an item in the stream_items table. The account is checked against the 26993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account in the raw contact for which the stream item is being inserted. If the 27003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * new stream item results in more stream items under this raw contact than the limit, 27013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the oldest one will be deleted (note that if the stream item inserted was the 27023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * oldest, it will be immediately deleted, and this will return 0). 27033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 27043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param uri the insertion URI 27053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param values the values for the new row 27063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return the stream item _ID of the newly created row, or 0 if it was not created 27073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 27083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long insertStreamItem(Uri uri, ContentValues values) { 27093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long id = 0; 27103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.clear(); 27113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.putAll(values); 27123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = mValues.getAsLong(StreamItems.RAW_CONTACT_ID); 27143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Ensure that the raw contact exists and belongs to the caller's account. 27163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, mValues); 27173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, rawContactId); 27183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27196802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to insert accounts params - they don't exist in the stream items table. 27206802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_NAME); 27216802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_TYPE); 27226802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 27233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Insert the new stream item. 27245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = mActiveDb.get().insert(Tables.STREAM_ITEMS, null, mValues); 27256802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (id == -1) { 27266802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Insertion failed. 27276802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return 0; 27286802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 27293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check to see if we're over the limit for stream items under this raw contact. 27313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // It's possible that the inserted stream item is older than the the existing 27323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // ones, in which case it may be deleted immediately (resetting the ID to 0). 27333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann id = cleanUpOldStreamItems(rawContactId, id); 27343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return id; 27363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 27373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 27393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Inserts an item in the stream_item_photos table. The account is checked against 27403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the account in the raw contact that owns the stream item being modified. 27413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 27423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param uri the insertion URI 27433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param values the values for the new row 27446802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @return the stream item photo _ID of the newly created row, or 0 if there was an issue 27456802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * with processing the photo or creating the row 27463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 27473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long insertStreamItemPhoto(Uri uri, ContentValues values) { 27483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long id = 0; 27493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.clear(); 27503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mValues.putAll(values); 27513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long streamItemId = mValues.getAsLong(StreamItemPhotos.STREAM_ITEM_ID); 27533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (streamItemId != 0) { 27543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = lookupRawContactIdForStreamId(streamItemId); 27553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Ensure that the raw contact exists and belongs to the caller's account. 27573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, mValues); 27583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, rawContactId); 27593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27606802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to insert accounts params - they don't exist in the stream item 27616802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // photos table. 27626802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_NAME); 27636802030a777c0c3ba1dc029c534cca4784260632Dave Santoro mValues.remove(RawContacts.ACCOUNT_TYPE); 27643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27656802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Process the photo and store it. 27666802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (processStreamItemPhoto(mValues, false)) { 27676802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Insert the stream item photo. 27685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro id = mActiveDb.get().insert(Tables.STREAM_ITEM_PHOTOS, null, mValues); 27696802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 27703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 27713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return id; 27723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 27733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 27743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 27756802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * Processes the photo contained in the {@link ContactsContract.StreamItemPhotos#PHOTO} 27766802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * field of the given values, attempting to store it in the photo store. If successful, 27776802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * the resulting photo file ID will be added to the values for insert/update in the table. 27786802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * <p> 27796802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * If updating, it is valid for the picture to be empty or unspecified (the function will 27806802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * still return true). If inserting, a valid picture must be specified. 27816802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @param values The content values provided by the caller. 27826802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @param forUpdate Whether this photo is being processed for update (vs. insert). 27836802030a777c0c3ba1dc029c534cca4784260632Dave Santoro * @return Whether the insert or update should proceed. 27846802030a777c0c3ba1dc029c534cca4784260632Dave Santoro */ 27856802030a777c0c3ba1dc029c534cca4784260632Dave Santoro private boolean processStreamItemPhoto(ContentValues values, boolean forUpdate) { 27866802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (!values.containsKey(StreamItemPhotos.PHOTO)) { 27876802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return forUpdate; 27886802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 27896802030a777c0c3ba1dc029c534cca4784260632Dave Santoro byte[] photoBytes = values.getAsByteArray(StreamItemPhotos.PHOTO); 27906802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoBytes == null) { 27916802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return forUpdate; 27926802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 27936802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 27946802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Process the photo and store it. 27956802030a777c0c3ba1dc029c534cca4784260632Dave Santoro try { 27965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long photoFileId = mPhotoStore.get().insert(new PhotoProcessor(photoBytes, 27971dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro mMaxDisplayPhotoDim, mMaxThumbnailPhotoDim, true), true); 27986802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (photoFileId != 0) { 27996802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.put(StreamItemPhotos.PHOTO_FILE_ID, photoFileId); 28006802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(StreamItemPhotos.PHOTO); 28016802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return true; 28026802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } else { 28036802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Couldn't store the photo, return 0. 28046802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Log.e(TAG, "Could not process stream item photo for insert"); 28056802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return false; 28066802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28076802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } catch (IOException ioe) { 28086802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Log.e(TAG, "Could not process stream item photo for insert", ioe); 28096802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return false; 28106802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28116802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 28126802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 28136802030a777c0c3ba1dc029c534cca4784260632Dave Santoro /** 28143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Looks up the raw contact ID that owns the specified stream item. 28153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param streamItemId The ID of the stream item. 28163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The associated raw contact ID, or -1 if no such stream item exists. 28173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 28183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long lookupRawContactIdForStreamId(long streamItemId) { 28193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = -1; 28205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, 28215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{StreamItems.RAW_CONTACT_ID}, 28223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItems._ID + "=?", new String[]{String.valueOf(streamItemId)}, 28233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 28243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 28253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (c.moveToFirst()) { 28263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann rawContactId = c.getLong(0); 28273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 28293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 28303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return rawContactId; 28323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 28343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 28353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given raw contact ID is owned by the given account. 28363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * If the resolved account is null, this will return true iff the raw contact 28373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * is also associated with the "null" account. 28383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 28393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * If the resolved account does not match, this will throw a security exception. 28403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 28413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param rawContactId The raw contact ID to check for. 28423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 28433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void enforceModifyingAccount(Account account, long rawContactId) { 28443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String accountSelection = RawContactsColumns.CONCRETE_ID + "=? AND " 28453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_NAME + "=? AND " 28463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + "=?"; 28473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String noAccountSelection = RawContactsColumns.CONCRETE_ID + "=? AND " 28483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " IS NULL AND " 28493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " IS NULL"; 28503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Cursor c; 28513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (account != null) { 28525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro c = mActiveDb.get().query(Tables.RAW_CONTACTS, 28535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{RawContactsColumns.CONCRETE_ID}, accountSelection, 28543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(rawContactId), mAccount.name, mAccount.type}, 28553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 28563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } else { 28575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro c = mActiveDb.get().query(Tables.RAW_CONTACTS, 28585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{RawContactsColumns.CONCRETE_ID}, noAccountSelection, 28595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{String.valueOf(rawContactId)}, 28603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, null); 28613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 28633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if(c.getCount() == 0) { 28643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann throw new SecurityException("Caller account does not match raw contact ID " 28653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + rawContactId); 28663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 28683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 28693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 28723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 28733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given selection of stream items matches up with the given 28743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account. If any of the raw contacts fail the account check, this will throw a 28753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * security exception. 28763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 28773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selection The selection. 28783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selectionArgs The selection arguments. 28793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The list of stream item IDs that would be included in this selection. 28803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 28813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private List<Long> enforceModifyingAccountForStreamItems(Account account, String selection, 28823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 28833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemIds = Lists.newArrayList(); 28843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 28853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 28865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), 28873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{StreamItems._ID, StreamItems.RAW_CONTACT_ID}, 28883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selection, selectionArgs, null, null, null); 28893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 28903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.moveToNext()) { 28913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann streamItemIds.add(c.getLong(0)); 28923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 28933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Throw a security exception if the account doesn't match the raw contact's. 28943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, c.getLong(1)); 28953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 28973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 28983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 28993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemIds; 29003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 29033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Checks whether the given selection of stream item photos matches up with the given 29043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * account. If any of the raw contacts fail the account check, this will throw a 29053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * security exception. 29063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param account The resolved account (may be null). 29073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selection The selection. 29083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param selectionArgs The selection arguments. 29093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The list of stream item photo IDs that would be included in this selection. 29103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 29113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private List<Long> enforceModifyingAccountForStreamItemPhotos(Account account, String selection, 29123b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 29133b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemPhotoIds = Lists.newArrayList(); 29143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 29153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 29165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), 29175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[]{StreamItemPhotos._ID, StreamItems.RAW_CONTACT_ID}, 29183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selection, selectionArgs, null, null, null); 29193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 29203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.moveToNext()) { 29213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann streamItemPhotoIds.add(c.getLong(0)); 29223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Throw a security exception if the account doesn't match the raw contact's. 29243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccount(account, c.getLong(1)); 29253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 29273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 29283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemPhotoIds; 29303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann /** 29333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * Queries the database for stream items under the given raw contact. If there are 29343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * more entries than {@link ContactsProvider2#MAX_STREAM_ITEMS_PER_RAW_CONTACT}, 29353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * the oldest entries (as determined by timestamp) will be deleted. 29363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param rawContactId The raw contact ID to examine for stream items. 29373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @param insertedStreamItemId The ID of the stream item that was just inserted, 29383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * prompting this cleanup. Callers may pass 0 if no insertion prompted the 29393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * cleanup. 29403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * @return The ID of the inserted stream item if it still exists after cleanup; 29413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann * 0 otherwise. 29423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann */ 29433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private long cleanUpOldStreamItems(long rawContactId, long insertedStreamItemId) { 29443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long postCleanupInsertedStreamId = insertedStreamItemId; 29455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, new String[]{StreamItems._ID}, 29463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItems.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)}, 29473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann null, null, StreamItems.TIMESTAMP + " DESC, " + StreamItems._ID + " DESC"); 29483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann try { 29493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann int streamItemCount = c.getCount(); 29503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (streamItemCount <= MAX_STREAM_ITEMS_PER_RAW_CONTACT) { 29513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Still under the limit - nothing to clean up! 29523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return insertedStreamItemId; 29533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } else { 29543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.moveToLast(); 29553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann while (c.getPosition() >= MAX_STREAM_ITEMS_PER_RAW_CONTACT) { 29563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long streamItemId = c.getLong(0); 29573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (insertedStreamItemId == streamItemId) { 29583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // The stream item just inserted is being deleted. 29593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann postCleanupInsertedStreamId = 0; 29603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItem(c.getLong(0)); 29623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.moveToPrevious(); 29633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } finally { 29663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann c.close(); 29673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return postCleanupInsertedStreamId; 29693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 29703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 29719261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 297220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 297320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2974f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 297520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 297620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2977de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 2978de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 29790c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro Uri dataUri = inProfileMode() 29800c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro ? Uri.withAppendedPath(Profile.CONTENT_URI, RawContacts.Data.CONTENT_DIRECTORY) 29810c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro : Data.CONTENT_URI; 29820c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro Cursor c = query(dataUri, DataRowHandler.DataDeleteQuery.COLUMNS, 2983f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov selection, selectionArgs, null); 2984de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 2985de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 2986f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov long rawContactId = c.getLong(DataRowHandler.DataDeleteQuery.RAW_CONTACT_ID); 2987f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE); 2988a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 29895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro count += rowHandler.delete(mActiveDb.get(), mTransactionContext.get(), c); 2990f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 29915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().markRawContactDirty(rawContactId); 299288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 299320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 299420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 2995de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 299620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 299720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 299820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 299920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 300020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 300188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 300288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 300388e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 300420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 3005f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 300688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 300788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 30084da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 3009f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataRowHandler.DataDeleteQuery.COLUMNS, Data._ID + "=?", 30104da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null); 3011f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 301220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 301320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 301420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 301520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 301620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3017f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE); 301820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 301920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 302020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 302120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 302220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 302320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 302420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 302520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 302620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 30277a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 302820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 302920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3030a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 30315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return rowHandler.delete(mActiveDb.get(), mTransactionContext.get(), c); 303220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 303320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 303420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 303520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 303620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 303720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 3038ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 3039ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 3040f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 3041f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 3042f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 3043f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 30443593682b8d9213fde576a0cff54458ad50563980Dave Santoro final AccountWithDataSet accountWithDataSet = resolveAccountWithDataSet(uri, mValues); 3045ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3046ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 3047f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String packageName = mValues.getAsString(Groups.RES_PACKAGE); 304867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 30495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.get().getPackageId(packageName)); 305067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 3051f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.remove(Groups.RES_PACKAGE); 3052ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3053dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final boolean isFavoritesGroup = mValues.getAsLong(Groups.FAVORITES) != null 3054dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ? mValues.getAsLong(Groups.FAVORITES) != 0 3055dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana : false; 3056dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3057f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 3058f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(Groups.DIRTY, 1); 305973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 306073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 30615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long result = mActiveDb.get().insert(Tables.GROUPS, Groups.TITLE, mValues); 3062ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 3063dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && isFavoritesGroup) { 3064dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // add all starred raw contacts to this group 3065dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String selection; 3066dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs; 30673593682b8d9213fde576a0cff54458ad50563980Dave Santoro if (accountWithDataSet == null) { 3068dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + " IS NULL AND " 306943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.ACCOUNT_TYPE + " IS NULL AND " 307043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.DATA_SET + " IS NULL"; 3071dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selectionArgs = null; 30723593682b8d9213fde576a0cff54458ad50563980Dave Santoro } else if (accountWithDataSet.getDataSet() == null) { 3073dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + "=? AND " 30743593682b8d9213fde576a0cff54458ad50563980Dave Santoro + RawContacts.ACCOUNT_TYPE + "=? AND " 30753593682b8d9213fde576a0cff54458ad50563980Dave Santoro + RawContacts.DATA_SET + " IS NULL"; 30763593682b8d9213fde576a0cff54458ad50563980Dave Santoro selectionArgs = new String[] { 30773593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountName(), 30783593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountType() 30793593682b8d9213fde576a0cff54458ad50563980Dave Santoro }; 308043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } else { 308143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro selection = RawContacts.ACCOUNT_NAME + "=? AND " 308243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.ACCOUNT_TYPE + "=? AND " 308343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + RawContacts.DATA_SET + "=?"; 30843593682b8d9213fde576a0cff54458ad50563980Dave Santoro selectionArgs = new String[] { 30853593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountName(), 30863593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getAccountType(), 30873593682b8d9213fde576a0cff54458ad50563980Dave Santoro accountWithDataSet.getDataSet() 30883593682b8d9213fde576a0cff54458ad50563980Dave Santoro }; 3089dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 30905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, 3091dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{RawContacts._ID, RawContacts.STARRED}, 3092dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection, selectionArgs, null, null, null); 3093892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov try { 3094892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov while (c.moveToNext()) { 3095892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (c.getLong(1) != 0) { 3096892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov final long rawContactId = c.getLong(0); 3097892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov insertDataGroupMembership(rawContactId, result); 30985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().markRawContactDirty(rawContactId); 3099892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 3100dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3101892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } finally { 3102892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov c.close(); 3103dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3104dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3105dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3106f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mValues.containsKey(Groups.GROUP_VISIBLE)) { 31071a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3108ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 3109ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 3110ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 3111ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3112ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 31135aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 31145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long id = mActiveDb.get().insert(Tables.SETTINGS, null, values); 31155aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 31161a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 31171a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3118e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 31191a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 3120e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 3121e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3122e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3123ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 312482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 31251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 312682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 312782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 31280a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 31294dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 31304dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 31310a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 313282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 31334dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 31344dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 31354dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 31364dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 31371f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 31381f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3139dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 3140dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 314182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 31426802030a777c0c3ba1dc029c534cca4784260632Dave Santoro String accountType = null; 31436802030a777c0c3ba1dc029c534cca4784260632Dave Santoro String accountName = null; 3144f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 31452526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.clear(); 3146dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 3147dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 3148dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 31492526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "=?"); 31502526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(dataId)); 31511f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 3152dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 3153dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 31540a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 31550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 31560a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 31570a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3158dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 3159dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 3160dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 31615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String mimeTypeIdIm = String.valueOf(mDbHelper.get().getMimeTypeIdForIm()); 3162dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 31635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String mimeTypeIdEmail = String.valueOf(mDbHelper.get().getMimeTypeIdForEmail()); 3164f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3165f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 3166f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 3167f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 3168f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3169f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 3170f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 31712526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (?,?)" + 31722526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Data.DATA1 + "=?" + 31732526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND ((" + DataColumns.MIMETYPE_ID + "=? AND " + Im.PROTOCOL + "=?"); 31742526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 31752526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 31762526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 31772526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 31782526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 3179dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 31802526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 31812526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3182dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 31832526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=?))"); 31842526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 3185dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 31862526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=?" + 31872526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.PROTOCOL + "=?" + 31882526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.DATA + "=?"); 31892526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 31902526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 31912526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 3192dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 31932526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 31942526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3195dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 3196dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 31971f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 319882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 31992526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=?"); 32002526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(values.getAsString(StatusUpdates.DATA_ID)); 3201dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 320270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 320370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 32041f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 32051f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 32065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro cursor = mActiveDb.get().query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 32072526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.toString(), mSelectionArgs.toArray(EMPTY_STRING_ARRAY), null, null, 32084394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov Clauses.CONTACT_VISIBLE + " DESC, " + Data.RAW_CONTACT_ID); 32091f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 321067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 32115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 32126802030a777c0c3ba1dc029c534cca4784260632Dave Santoro accountType = cursor.getString(DataContactsQuery.ACCOUNT_TYPE); 32136802030a777c0c3ba1dc029c534cca4784260632Dave Santoro accountName = cursor.getString(DataContactsQuery.ACCOUNT_NAME); 3214e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 32151f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 32161f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 32171f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 32181f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 32191f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 322031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 322131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 322231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 32231f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 32241f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 322582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 3226a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 3227a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 3228a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 3229a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 3230a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3231a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3232a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 323382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 3234a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 3235a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 323682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 323782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 323882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 323982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 324082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 3241a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 324282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 324382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 3244aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori mValues.put(StatusUpdates.CHAT_CAPABILITY, 3245aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori values.getAsString(StatusUpdates.CHAT_CAPABILITY)); 32461f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3247a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 32485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().replace(Tables.PRESENCE, null, mValues); 3249a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3250e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 32510a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 325282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 325382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 32540a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 32550bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Resources resources = getContext().getResources(); 32560bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if (!TextUtils.isEmpty(resPackage)) { 32570bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann PackageManager pm = getContext().getPackageManager(); 32580bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann try { 32590bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann resources = pm.getResourcesForApplication(resPackage); 32600bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } catch (NameNotFoundException e) { 32610bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Log.w(TAG, "Contact status update resource package not found: " 32620bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + resPackage); 32630bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 32640bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 32650bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Integer labelResourceId = values.getAsInteger(StatusUpdates.STATUS_LABEL); 32660a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 32670bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if ((labelResourceId == null || labelResourceId == 0) && protocol != null) { 32680bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann labelResourceId = Im.getProtocolLabelResource(protocol); 32690a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 32700bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann String labelResource = getResourceName(resources, "string", labelResourceId); 32710a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 32720bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Integer iconResourceId = values.getAsInteger(StatusUpdates.STATUS_ICON); 32730a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 32740a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 32750bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann String iconResource = getResourceName(resources, "drawable", iconResourceId); 32760bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 3277a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 32785d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().deleteStatusUpdate(dataId); 3279a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 32806802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 32816802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (timestamp != null) { 32825d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().replaceStatusUpdate(dataId, timestamp, status, resPackage, 32830bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann iconResourceId, labelResourceId); 32846802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } else { 32855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().insertStatusUpdate(dataId, status, resPackage, iconResourceId, 32860bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann labelResourceId); 32876802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 32886802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 32896802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // For forward compatibility with the new stream item API, insert this status update 32906802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // there as well. If we already have a stream item from this source, update that 32916802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // one instead of inserting a new one (since the semantics of the old status update 32926802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // API is to only have a single record). 32936802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (rawContactId != -1 && !TextUtils.isEmpty(status)) { 32946802030a777c0c3ba1dc029c534cca4784260632Dave Santoro ContentValues streamItemValues = new ContentValues(); 32956802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RAW_CONTACT_ID, rawContactId); 3296d5ef5903570e533a501abe6a8e3d533fdb5318fcFlavio Lerda // Status updates are text only but stream items are HTML. 3297e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda streamItemValues.put(StreamItems.TEXT, statusUpdateToHtml(status)); 32986802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.COMMENTS, ""); 32996802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RES_PACKAGE, resPackage); 33006802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RES_ICON, iconResource); 33016802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.RES_LABEL, labelResource); 33026802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(StreamItems.TIMESTAMP, 33036802030a777c0c3ba1dc029c534cca4784260632Dave Santoro timestamp == null ? System.currentTimeMillis() : timestamp); 33046802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 33056802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Note: The following is basically a workaround for the fact that status 33066802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // updates didn't do any sort of account enforcement, while social stream item 33076802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // updates do. We can't expect callers of the old API to start passing account 33086802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // information along, so we just populate the account params appropriately for 330943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // the raw contact. Data set is not relevant here, as we only check account 331043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // name and type. 33116802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (accountName != null && accountType != null) { 33126802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(RawContacts.ACCOUNT_NAME, accountName); 33136802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues.put(RawContacts.ACCOUNT_TYPE, accountType); 33146802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 33156802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 33166802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Check for an existing stream item from this source, and insert or update. 33176802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Uri streamUri = StreamItems.CONTENT_URI; 33186802030a777c0c3ba1dc029c534cca4784260632Dave Santoro Cursor c = query(streamUri, new String[]{StreamItems._ID}, 33196802030a777c0c3ba1dc029c534cca4784260632Dave Santoro StreamItems.RAW_CONTACT_ID + "=?", 33206802030a777c0c3ba1dc029c534cca4784260632Dave Santoro new String[]{String.valueOf(rawContactId)}, null); 33216802030a777c0c3ba1dc029c534cca4784260632Dave Santoro try { 33226802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (c.getCount() > 0) { 33236802030a777c0c3ba1dc029c534cca4784260632Dave Santoro c.moveToFirst(); 33246802030a777c0c3ba1dc029c534cca4784260632Dave Santoro update(ContentUris.withAppendedId(streamUri, c.getLong(0)), 33256802030a777c0c3ba1dc029c534cca4784260632Dave Santoro streamItemValues, null, null); 33266802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } else { 33276802030a777c0c3ba1dc029c534cca4784260632Dave Santoro insert(streamUri, streamItemValues); 33286802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 33296802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } finally { 33306802030a777c0c3ba1dc029c534cca4784260632Dave Santoro c.close(); 33316802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 33326802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 3333e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3334e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3335bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 3336a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 33375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateLastStatusUpdateId(contactId); 3338a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3339a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3340a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 33411f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 33421f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3343e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda /** Converts a status update to HTML. */ 3344e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda private String statusUpdateToHtml(String status) { 33454747809486541f7a3d342d3e1dd48fb5ea255ad6Flavio Lerda return TextUtils.htmlEncode(status); 3346e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda } 3347e3a10e4fcdb8b5e619f02a26fd1a26cef3b149a3Flavio Lerda 33480bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann private String getResourceName(Resources resources, String expectedType, Integer resourceId) { 33490bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann try { 33500bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if (resourceId == null || resourceId == 0) return null; 33510bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 33520bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann // Resource has an invalid type (e.g. a string as icon)? ignore 33530bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann final String resourceEntryName = resources.getResourceEntryName(resourceId); 33540bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann final String resourceTypeName = resources.getResourceTypeName(resourceId); 33550bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann if (!expectedType.equals(resourceTypeName)) { 33560bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann Log.w(TAG, "Resource " + resourceId + " (" + resourceEntryName + ") is of type " + 33570bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann resourceTypeName + " but " + expectedType + " is required."); 33580bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann return null; 33590bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 33600bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 33610bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann return resourceEntryName; 33620bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } catch (NotFoundException e) { 33630bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann return null; 33640bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 33650bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann } 33660bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann 33674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3368de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 3369bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3370b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 3371b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 33725d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 33735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 33745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 33755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 33765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 33775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 3378b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3379f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3380f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 3381508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 3382508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 338335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 33845d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 33855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().delete(mActiveDb.get(), selection, 33865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 33875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 33885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case SYNCSTATE_ID: { 33895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String selectionWithId = 33905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 33915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro + (selection == null ? "" : " AND (" + selection + ")"); 33925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().delete(mActiveDb.get(), selectionWithId, 33935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 33945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 339535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 33965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE_ID: { 3397b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3398b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3399b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 34005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileHelper.getSyncState().delete(mActiveDb.get(), selectionWithId, 34015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 34025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 3403b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3404cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 3405cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 3406cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 3407cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3408cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3409d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3410d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3411dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 34126bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 34136bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 34149fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP: { 34152e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 34162e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 34172e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 34185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 3419fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 34202e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 34212e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 34225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 3423dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 34242e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 34252e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 34269fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP_ID: { 34279fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // lookup contact by id and lookup key to see if they still match the actual record 34289fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final List<String> pathSegments = uri.getPathSegments(); 34299fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final String lookupKey = pathSegments.get(2); 34309fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 34319fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann setTablesAndProjectionMapForContacts(lookupQb, uri, null); 3432a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 34339fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann String[] args; 34349fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (selectionArgs == null) { 34359fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[2]; 34369fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 34379fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[selectionArgs.length + 2]; 34389fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 34399fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34409fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args[0] = String.valueOf(contactId); 344160de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann args[1] = Uri.encode(lookupKey); 34429fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 34435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = query(mActiveDb.get(), lookupQb, null, selection, args, null, null, 34445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro null); 34459fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann try { 34469fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (c.getCount() == 1) { 34479fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // contact was unmodified so go ahead and delete it 3448dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 34499fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 34509fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // row was changed (e.g. the merging might have changed), we got multiple 34519fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // rows or the supplied selection filtered the record out 34529fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return 0; 34539fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34549fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } finally { 34559fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann c.close(); 34569fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34579fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34589fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 34592971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 34602971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 34615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, 3462fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov new String[]{RawContacts._ID, RawContacts.CONTACT_ID}, 3463e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 34642971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 34652971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 34662971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 3467fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov long contactId = c.getLong(1); 3468fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov numDeletes += deleteRawContact(rawContactId, contactId, 3469fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 34702971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 34712971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 34722971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 34732971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 34742971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 34752971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 34762971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 34775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 34782971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 34795d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return deleteRawContact(rawContactId, mDbHelper.get().getContactId(rawContactId), 3480fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 3481508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3482508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 34830c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case DATA: 34840c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case PROFILE_DATA: { 3485f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 3486944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 3487f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 348820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 348920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 349048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 349148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 349248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 349348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3494508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 3495f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 34964da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 34974da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return deleteData(Data._ID + "=?", mSelectionArgs1, callerIsSyncAdapter); 3498ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3499ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3500ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3501f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 35025aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 35032971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35042971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 35052971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 35062971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 35075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.GROUPS, new String[]{Groups._ID}, 3508e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 35092971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 35102971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 35115aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 35122971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 35132971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 35142971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 35152971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 351681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 3517f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 351881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 35192971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 3520508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3521508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 3522eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 352343880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3524e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return deleteSettings(uri, appendAccountToSelection(uri, selection), selectionArgs); 3525eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3526eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 35275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 35285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 35290a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 35301f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 35311f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 35323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 35333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 35343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItems(uri, new ContentValues(), selection, selectionArgs); 35353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 35363b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 35373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 35383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 35393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItems(uri, new ContentValues(), 35409b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann StreamItems._ID + "=?", 35413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{uri.getLastPathSegment()}); 35423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 35433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 354482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro case RAW_CONTACTS_ID_STREAM_ITEMS_ID: { 354582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro mSyncToNetwork |= !callerIsSyncAdapter; 354682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String rawContactId = uri.getPathSegments().get(1); 354782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String streamItemId = uri.getLastPathSegment(); 354882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro return deleteStreamItems(uri, new ContentValues(), 354982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems.RAW_CONTACT_ID + "=? AND " + StreamItems._ID + "=?", 355082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro new String[]{rawContactId, streamItemId}); 355182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 355282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 355382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 35543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 35553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 35565d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro String streamItemId = uri.getPathSegments().get(1); 35575d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro String selectionWithId = 35585d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro (StreamItemPhotos.STREAM_ITEM_ID + "=" + streamItemId + " ") 35595d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro + (selection == null ? "" : " AND (" + selection + ")"); 35605d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro return deleteStreamItemPhotos(uri, new ContentValues(), 35615d9fcbaaa0007134564d63272470296f5d23b62aDave Santoro selectionWithId, selectionArgs); 35623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 35633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 35643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 35653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mSyncToNetwork |= !callerIsSyncAdapter; 35663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 35673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 35683b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return deleteStreamItemPhotos(uri, new ContentValues(), 35693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=? AND " 35703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann + StreamItemPhotos.STREAM_ITEM_ID + "=?", 35713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{streamItemPhotoId, streamItemId}); 35723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 35733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 357481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 357581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 35763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 357781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3578508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 35794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 35811c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 3582ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 35835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long groupMembershipMimetypeId = mDbHelper.get() 358494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 35855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 358694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 358794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 358894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 358994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 3590f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 35915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 359294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 359394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 359494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 3595f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 35965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, 35975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro null); 359894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 359994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 36001a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 360194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 360294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 360394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 36045aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 36055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final int count = mActiveDb.get().delete(Tables.SETTINGS, selection, selectionArgs); 36061a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3607e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3608e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3609e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3610dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int deleteContact(long contactId, boolean callerIsSyncAdapter) { 361196b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(contactId); 36125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 361396b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker RawContacts.CONTACT_ID + "=?", mSelectionArgs1, 361496b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker null, null, null); 3615cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 3616cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 3617cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 3618dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 3619cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3620cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 3621cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 3622cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3623cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 36243826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 36253826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 36265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 3627cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3628cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3629fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) { 36305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().invalidateAggregationExceptionCache(); 36313826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mProviderStatusUpdateNeeded = true; 36323826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 363382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro // Find and delete stream items associated with the raw contact. 363482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, 363582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro new String[]{StreamItems._ID}, 363682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)}, 363782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro null, null, null); 363882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro try { 363982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro while (c.moveToNext()) { 364082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro deleteStreamItem(c.getLong(0)); 364182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 364282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } finally { 364382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro c.close(); 364482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 364582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 3646f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 36475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.PRESENCE, 36485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 36495d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int count = mActiveDb.get().delete(Tables.RAW_CONTACTS, 36505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro RawContacts._ID + "=" + rawContactId, null); 36515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateDisplayNameForContact(mActiveDb.get(), contactId); 3652fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return count; 365333b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 36545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().removeContactIfSingleton(rawContactId); 3655dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 365633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 365733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 365833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 36590a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 36609705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // delete from both tables: presence and status_updates 36619705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 36629705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (VERBOSE_LOGGING) { 36639705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Log.v(TAG, "deleting data from status_updates for " + selection); 36649705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 36655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 36669705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 36675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.PRESENCE, selection, selectionArgs); 36680a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 36690a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 36703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItems(Uri uri, ContentValues values, String selection, 36713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 36723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // First query for the stream items to be deleted, and check that they belong 36733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // to the account. 36743b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 36753b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<Long> streamItemIds = enforceModifyingAccountForStreamItems( 36763b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann account, selection, selectionArgs); 36773b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 36783b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If no security exception has been thrown, we're fine to delete. 36793b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann for (long streamItemId : streamItemIds) { 36803b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItem(streamItemId); 36813b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 36823b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 36833b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann mVisibleTouched = true; 36843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return streamItemIds.size(); 36853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 36863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 36873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItem(long streamItemId) { 36883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Note that this does not enforce the modifying account. 36893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann deleteStreamItemPhotos(streamItemId); 36905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.STREAM_ITEMS, StreamItems._ID + "=?", 36913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(streamItemId)}); 36923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 36933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 36943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItemPhotos(Uri uri, ContentValues values, String selection, 36953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 36963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // First query for the stream item photos to be deleted, and check that they 36973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // belong to the account. 36983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 36993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItemPhotos(account, selection, selectionArgs); 37003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If no security exception has been thrown, we're fine to delete. 37025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.STREAM_ITEM_PHOTOS, selection, selectionArgs); 37033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 37053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int deleteStreamItemPhotos(long streamItemId) { 37063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Note that this does not enforce the modifying account. 37075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().delete(Tables.STREAM_ITEM_PHOTOS, 37085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro StreamItemPhotos.STREAM_ITEM_ID + "=?", 37093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{String.valueOf(streamItemId)}); 37103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 37113b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 3712dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int markRawContactAsDeleted(long rawContactId, boolean callerIsSyncAdapter) { 371381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 371481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 3715cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 3716cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 3717cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 3718cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 3719cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 3720cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3721dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return updateRawContact(rawContactId, mValues, callerIsSyncAdapter); 3722cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3723cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 37244f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3725de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 3726de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 3727bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3728b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 3729b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3730b5a4add17815167d20a90645779df34cdf45280dFred Quintana 37315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 37325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 37335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 37345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 37355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 373635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 373700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 373800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 3739b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 3740b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 37411129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Object data = values.get(ContactsContract.SyncState.DATA); 37425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().syncStateUpdated(rowId, data); 3743b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 3744b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3745b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3746f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3747f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 374800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 374935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 37505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 37515d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().update(mActiveDb.get(), values, 3752b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 3753b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3754b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 3755b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 3756b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3757b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3758b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 37595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().update(mActiveDb.get(), values, 37605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionWithId, selectionArgs); 37615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 37625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 37635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE_ID: { 37645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection = appendAccountToSelection(uri, selection); 37655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String selectionWithId = 37665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 37675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro + (selection == null ? "" : " AND (" + selection + ")"); 37685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileHelper.getSyncState().update(mActiveDb.get(), values, 3769b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 3770b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 377135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3772d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 3773dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(values, selection, selectionArgs, callerIsSyncAdapter); 377400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 377500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 377600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3777d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3778dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(ContentUris.parseId(uri), values, callerIsSyncAdapter); 3779c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 3780c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 3781c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 378224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: { 37835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro count = updateContactOptions(values, selection, selectionArgs, callerIsSyncAdapter); 378424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 378524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 378624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 37872e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 37882e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 37892e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 37902e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 37912e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 37925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 3793fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 37942e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 37952e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 37965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 3797dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(contactId, values, callerIsSyncAdapter); 37982e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 37992e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 38002e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 38017d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 38027d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 38037d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 38047d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 38057d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 38067d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 38077d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 38087d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 38097d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 38107d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 38110c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case DATA: 38120c5812a467378c57c2d2715ee4f0a9f541c64809Dave Santoro case PROFILE_DATA: { 3813944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 3814f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 381581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3816f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 381781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 381820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 381920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3820c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 382148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 382248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 382348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 382448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3825f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 382681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3827f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 382881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 382900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 383000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 38317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 38325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case RAW_CONTACTS: 38335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_RAW_CONTACTS: { 38345ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 3835dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, selection, selectionArgs, callerIsSyncAdapter); 38367e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 38377e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 38387e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 38395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 384033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 38414529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 38424da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 38434da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?" 3844dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND(" + selection + ")", selectionArgs, 3845dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 38464529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 38474da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 3848dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, RawContacts._ID + "=?", mSelectionArgs1, 3849dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 38504529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 38517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 38527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 38537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3854ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 38555aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 3856f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 385781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3858f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 385981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3860ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3861ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3862ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3863ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3864ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 38654da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(groupId)); 38664da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String selectionWithId = Groups._ID + "=? " 386773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 38685aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 38695aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 387081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3871f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 387281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3873ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3874ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3875ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3876127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 38775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro count = updateAggregationException(mActiveDb.get(), values); 3878b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3879b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3880b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3881eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3882e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey count = updateSettings(uri, values, appendAccountToSelection(uri, selection), 3883e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey selectionArgs); 388443880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3885eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3886eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3887eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 38885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 38895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 38909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori count = updateStatusUpdate(uri, values, selection, selectionArgs); 38919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori break; 38929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 38939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 38943b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 38953b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItems(uri, values, selection, selectionArgs); 38963b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 38973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 38983b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 38993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 39009b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann count = updateStreamItems(uri, values, StreamItems._ID + "=?", 39013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{uri.getLastPathSegment()}); 39023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 390582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro case RAW_CONTACTS_ID_STREAM_ITEMS_ID: { 390682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String rawContactId = uri.getPathSegments().get(1); 390782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro String streamItemId = uri.getLastPathSegment(); 390882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro count = updateStreamItems(uri, values, 390982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems.RAW_CONTACT_ID + "=? AND " + StreamItems._ID + "=?", 391082780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro new String[]{rawContactId, streamItemId}); 391182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro break; 391282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 391382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 39143b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 39153b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, selection, selectionArgs); 39163b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39173b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39183b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 39193b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 39203b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 39213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, 39223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotos.STREAM_ITEM_ID + "=?", new String[]{streamItemId}); 39233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 39263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 39273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 39283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 39293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann count = updateStreamItemPhotos(uri, values, 39303b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=? AND " + 39313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=?", 39323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann new String[]{streamItemPhotoId, streamItemId}); 39333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 39343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 39353b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 393672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov case DIRECTORIES: { 3937bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mContactDirectoryManager.scanPackagesByUid(Binder.getCallingUid()); 393872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov count = 1; 3939d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 3940d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3941d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 394246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa case DATA_USAGE_FEEDBACK_ID: { 394346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (handleDataUsageFeedback(uri)) { 394446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa count = 1; 394546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 394646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa count = 0; 394746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 394846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa break; 394946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 395046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 395181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 395281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 3953f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 395481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 395500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 395600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 395700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 39584f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 39594f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 39609705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 39619705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori String[] selectionArgs) { 39629705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // update status_updates table, if status is provided 39639705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 39649705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori int updateCount = 0; 39659705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 39669705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 39675d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro updateCount = mActiveDb.get().update(Tables.STATUS_UPDATES, 39689705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues, 39699705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori getWhereClauseForStatusUpdatesTable(selection), 39709705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 39719705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 39729705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 39739705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // now update the Presence table 39749705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues = getSettableColumnsForPresenceTable(values); 39759705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 39765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro updateCount = mActiveDb.get().update(Tables.PRESENCE, settableValues, 39779705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selection, selectionArgs); 39789705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 39799705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 39809705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // potentially get updated in this method. 39819705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return updateCount; 39829705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 39839705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 39843b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int updateStreamItems(Uri uri, ContentValues values, String selection, 39853b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 39863b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Stream items can't be moved to a new raw contact. 39873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.remove(StreamItems.RAW_CONTACT_ID); 39883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 39893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check that the stream items being updated belong to the account. 39903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 39913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItems(account, selection, selectionArgs); 39923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 39936802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to update accounts params - they don't exist in the stream items table. 39946802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_NAME); 39956802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_TYPE); 39966802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 39973b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // If there's been no exception, the update should be fine. 39985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().update(Tables.STREAM_ITEMS, values, selection, selectionArgs); 39993b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 40003b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40013b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private int updateStreamItemPhotos(Uri uri, ContentValues values, String selection, 40023b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String[] selectionArgs) { 40033b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Stream item photos can't be moved to a new stream item. 40043b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann values.remove(StreamItemPhotos.STREAM_ITEM_ID); 40053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40063b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann // Check that the stream item photos being updated belong to the account. 40073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann Account account = resolveAccount(uri, values); 40083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann enforceModifyingAccountForStreamItemPhotos(account, selection, selectionArgs); 40093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40106802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Don't attempt to update accounts params - they don't exist in the stream item 40116802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // photos table. 40126802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_NAME); 40136802030a777c0c3ba1dc029c534cca4784260632Dave Santoro values.remove(RawContacts.ACCOUNT_TYPE); 40146802030a777c0c3ba1dc029c534cca4784260632Dave Santoro 40156802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // Process the photo (since we're updating, it's valid for the photo to not be present). 40166802030a777c0c3ba1dc029c534cca4784260632Dave Santoro if (processStreamItemPhoto(values, true)) { 40176802030a777c0c3ba1dc029c534cca4784260632Dave Santoro // If there's been no exception, the update should be fine. 40185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().update(Tables.STREAM_ITEM_PHOTOS, values, selection, 40195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 40206802030a777c0c3ba1dc029c534cca4784260632Dave Santoro } 40216802030a777c0c3ba1dc029c534cca4784260632Dave Santoro return 0; 40223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 40233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 40249705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 40259705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Build a where clause to select the rows to be updated in status_updates table. 40269705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 40279705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private String getWhereClauseForStatusUpdatesTable(String selection) { 40289705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.setLength(0); 40299705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 40309705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(selection); 40319705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(")"); 40329705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mSb.toString(); 40339705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40349705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 40359705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 40369705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 40379705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 40389705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS); 40399705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 40409705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_TIMESTAMP); 40419705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 40429705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_RES_PACKAGE); 40439705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 40449705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_LABEL); 40459705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 40469705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_ICON); 40479705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 40489705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40499705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 40509705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 40519705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 40529705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 40539705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.PRESENCE); 4054aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.CHAT_CAPABILITY, values, 4055aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori StatusUpdates.CHAT_CAPABILITY); 40569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 40579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 40589705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 40595aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 4060f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 406173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 4062ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 4063ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 406473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 4065f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 406673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 406773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 406873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 406973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 407073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 407173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 407273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 407373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 40745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int count = mActiveDb.get().update(Tables.GROUPS, updatedValues, selectionWithId, 40755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs); 40761a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 40771a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 407894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 407943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 408043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // TODO: This will not work for groups that have a data set specified, since the content 408143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // resolver will not be able to request a sync for the right source (unless it is updated 408243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // to key off account with data set). 40836ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 40841129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 40855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 4086e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey Groups.ACCOUNT_TYPE}, selectionWithId, selectionArgs, null, 40876ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 40886ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 40896ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 40906ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 40916ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 40926ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 40936ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 409424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 40956ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 4096ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 40976ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 40986ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 40996ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 41006ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 41016ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 41026ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 41036ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 41046ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 410594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 410694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 410794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 4108b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 4109b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 41105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final int count = mActiveDb.get().update(Tables.SETTINGS, values, selection, selectionArgs); 41111a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 41121a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 4113e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4114e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 4115e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4116e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4117dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs, 4118dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 41194529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 41204529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 41214529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 41224529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 412373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 412497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 412597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 412697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0"); 412797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 412897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 41294529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 41305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(Views.RAW_CONTACTS, 413151bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 41324529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 41334529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 41344529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 41354529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 4136dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateRawContact(rawContactId, values, callerIsSyncAdapter); 41374529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 41384529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 41394529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 41404529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 41414529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 41424529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 41434529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 41444529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 41454529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 4146dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContact(long rawContactId, ContentValues values, 4147dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 414896b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker final String selection = RawContacts._ID + " = ?"; 414996b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(rawContactId); 415019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 415119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 415219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 4153ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = null; 4154ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = null; 415543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String dataSet = null; 415619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 41575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, 41585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection, mSelectionArgs1, null, null, null); 415919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 416019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 416119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 4162ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 4163ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 416443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro dataSet = cursor.getString(RawContactsQuery.DATA_SET); 416519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 416619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 416719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 416819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 416919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 417019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 417119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 4172f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 41735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int count = mActiveDb.get().update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1); 41745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 4175f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (values.containsKey(RawContacts.AGGREGATION_MODE)) { 4176f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = values.getAsInteger(RawContacts.AGGREGATION_MODE); 4177f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov 4178f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // As per ContactsContract documentation, changing aggregation mode 4179f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // to DEFAULT should not trigger aggregation 4180f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (aggregationMode != RawContacts.AGGREGATION_MODE_DEFAULT) { 41815d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markForAggregation(rawContactId, aggregationMode, false); 4182f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 4183f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 4184433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 4185dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 4186dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 4187dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana values.getAsLong(RawContacts.STARRED) != 0); 4188dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 41895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateStarred(rawContactId); 4190dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 4191dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then update the 4192dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // favorites group membership based on whether or not this contact is starred. 4193dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // If it is starred, add a group membership, if one doesn't already exist 4194dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // otherwise delete any matching group memberships. 4195dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 41965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro boolean starred = 0 != DatabaseUtils.longForQuery(mActiveDb.get(), 4197dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana SELECTION_STARRED_FROM_RAW_CONTACTS, 4198dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}); 4199dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred); 4200dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4201dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4202dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 4203dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then add a 4204dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // group membership to the group marked as AutoAdd, if any. 4205dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 4206dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 4207433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 4208dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 4209285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 42105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateLookupKeyForRawContact(mActiveDb.get(), rawContactId); 4211285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 4212f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.containsKey(RawContacts.NAME_VERIFIED)) { 4213f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 4214f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // If setting NAME_VERIFIED for this raw contact, reset it for all 4215f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // other raw contacts in the same aggregate 4216f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.getAsInteger(RawContacts.NAME_VERIFIED) != 0) { 42175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().resetNameVerifiedForOtherRawContacts(rawContactId); 4218f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 42195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateDisplayNameForRawContact(mActiveDb.get(), rawContactId); 4220f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 422119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 42225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mTransactionContext.get().rawContactInserted(rawContactId, 422343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new AccountWithDataSet(accountName, accountType, dataSet)); 422419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 42255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 422733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 422833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 4229321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 4230f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 423120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 423220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 423320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 42345ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 423520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 423620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 423720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 423820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 423920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 42405d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mValues.put(DataColumns.PACKAGE_ID, mDbHelper.get().getPackageId(packageName)); 424120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 424220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 424397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov if (!callerIsSyncAdapter) { 424497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov selection = DatabaseUtils.concatenateWhere(selection, 424597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov Data.IS_READ_ONLY + "=0"); 424697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 424797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 4248653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 424920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4250653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 4251653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 42525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryLocal(uri, 4253f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro DataRowHandler.DataUpdateQuery.COLUMNS, 42545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection, selectionArgs, null, -1 /* directory ID */); 4255653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 4256653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 4257f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 425820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 4259653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 4260653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 426120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 426220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4263653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 426420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 426520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4266f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 4267653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 4268653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 4269321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 4270653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 4271f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov final String mimeType = c.getString(DataRowHandler.DataUpdateQuery.MIMETYPE); 4272a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 4273f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro boolean updated = 42745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro rowHandler.update(mActiveDb.get(), mTransactionContext.get(), values, c, 42755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro callerIsSyncAdapter); 4276f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) { 4277f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS); 4278a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 4279f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return updated ? 1 : 0; 4280321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 4281321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 42828c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 4283dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 42848c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 42855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(Views.CONTACTS, 42865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro new String[] { Contacts._ID }, selection, selectionArgs, null, null, null); 42878c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 42888c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 42898c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 429024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 4291dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateContactOptions(contactId, values, callerIsSyncAdapter); 42928c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 42938c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 42948c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 42958c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 42968c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 42978c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 42988c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 42998c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 43008c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 4301dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateContactOptions(long contactId, ContentValues values, 4302dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 4303d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 43048c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 4305b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 4306d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 4307b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 4308d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 4309b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 4310d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 4311b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 4312d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 4313b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 4314d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 4315d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 4316d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 43178c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 4318d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 4319d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 4320d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 43218c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 4322c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 43238c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 4324c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 4325c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 43264da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 43275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?" 432897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov + " AND " + RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0", mSelectionArgs1); 43298c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 4330dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (mValues.containsKey(RawContacts.STARRED) && !callerIsSyncAdapter) { 43315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().query(Views.RAW_CONTACTS, 4332dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[] { RawContacts._ID }, RawContacts.CONTACT_ID + "=?", 4333dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mSelectionArgs1, null, null, null); 4334dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 4335dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (cursor.moveToNext()) { 4336dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana long rawContactId = cursor.getLong(0); 4337dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 4338dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.getAsLong(RawContacts.STARRED) != 0); 4339dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4340dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 4341dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana cursor.close(); 4342dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4343dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4344dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 43458c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 43468c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 43478c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 4348b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 43498c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 4350b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 43518c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 4352b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 43538c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 4354b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 43558c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 4356b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 43578c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 43588c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 43595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int rslt = mActiveDb.get().update(Tables.CONTACTS, mValues, Contacts._ID + "=?", 43605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mSelectionArgs1); 43616e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori 43629b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori if (values.containsKey(Contacts.LAST_TIME_CONTACTED) && 43639b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori !values.containsKey(Contacts.TIMES_CONTACTED)) { 43645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 43655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 43669b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori } 43679b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori return rslt; 4368f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 4369d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 4370127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 4371127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 43720c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 43730c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 437480c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 4375ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov long rawContactId1; 4376ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov long rawContactId2; 43770c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 43780c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 43790c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 43800c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 43810c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 43820c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 4383b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4384127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 43850c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 43864da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[0] = String.valueOf(rawContactId1); 43874da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[1] = String.valueOf(rawContactId2); 43880c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 43894da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=? AND " 43904da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=?", mSelectionArgs2); 43910c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 43926bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 43936bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 43940c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 43950c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 43960c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 43970c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 4398127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 4399127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 44005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().invalidateAggregationExceptionCache(); 44015d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markForAggregation(rawContactId1, 440269cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 44035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().markForAggregation(rawContactId2, 440469cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 4405dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 44065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().aggregateContact(mTransactionContext.get(), db, rawContactId1); 44075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().aggregateContact(mTransactionContext.get(), db, rawContactId2); 4408127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 4409127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 4410127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 4411127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 4412b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4413b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 441470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 4415bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS); 44163826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 44173826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 4418bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected boolean updateAccountsInBackground(Account[] accounts) { 4419f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao // TODO : Check the unit test. 4420e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov boolean accountsChanged = false; 44215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mDbHelper.get().getWritableDatabase(); 44225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(db); 44235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.beginTransaction(); 442470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 442543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Set<AccountWithDataSet> existingAccountsWithDataSets = 442643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro findValidAccountsWithDataSets(Tables.ACCOUNTS); 4427743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov 442843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Add a row to the ACCOUNTS table (with no data set) for each new account. 4429743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov for (Account account : accounts) { 443043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro AccountWithDataSet accountWithDataSet = new AccountWithDataSet( 443143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro account.name, account.type, null); 443243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (!existingAccountsWithDataSets.contains(accountWithDataSet)) { 4433e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 443443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 443543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Add an account entry with an empty data set to match the account. 44365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 443743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ", " + RawContacts.ACCOUNT_TYPE + ", " + RawContacts.DATA_SET 443843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ") VALUES (?, ?, ?)", 443943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new String[] { 444043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 444143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType(), 444243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getDataSet() 444343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }); 4444743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 4445743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 444648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 444743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Check each of the existing sub-accounts against the account list. If the owning 444843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // account no longer exists, the sub-account and all its data should be deleted. 444943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro List<AccountWithDataSet> accountsWithDataSetsToDelete = 445043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new ArrayList<AccountWithDataSet>(); 445143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro List<Account> accountList = Arrays.asList(accounts); 445243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro for (AccountWithDataSet accountWithDataSet : existingAccountsWithDataSets) { 445343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Account owningAccount = new Account( 445443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), accountWithDataSet.getAccountType()); 445543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (!accountList.contains(owningAccount)) { 445643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountsWithDataSetsToDelete.add(accountWithDataSet); 445743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 445870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 445970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 446043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (!accountsWithDataSetsToDelete.isEmpty()) { 4461e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov accountsChanged = true; 446243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro for (AccountWithDataSet accountWithDataSet : accountsWithDataSetsToDelete) { 446343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Log.d(TAG, "removing data for removed account " + accountWithDataSet); 446443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String[] accountParams = new String[] { 446543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 446643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType() 446743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }; 446843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String[] accountWithDataSetParams = accountWithDataSet.getDataSet() == null 446943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ? accountParams 447043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro : new String[] { 447143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 447243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType(), 447343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getDataSet() 447443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }; 447543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String groupsDataSetClause = " AND " + Groups.DATA_SET 447643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + (accountWithDataSet.getDataSet() == null ? " IS NULL" : " = ?"); 447743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String rawContactsDataSetClause = " AND " + RawContacts.DATA_SET 447843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + (accountWithDataSet.getDataSet() == null ? " IS NULL" : " = ?"); 447943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 44805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4481e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.GROUPS + 4482e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 448343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + Groups.ACCOUNT_TYPE + " = ?" + 448443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro groupsDataSetClause, accountWithDataSetParams); 44855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4486e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 4487e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 4488e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "SELECT " + RawContacts._ID + 4489e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 4490e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 449143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 449243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactsDataSetClause + ")", accountWithDataSetParams); 44935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4494c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "DELETE FROM " + Tables.STREAM_ITEM_PHOTOS + 4495c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + StreamItemPhotos.STREAM_ITEM_ID + " IN (" + 4496c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "SELECT " + StreamItems._ID + 4497c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " FROM " + Tables.STREAM_ITEMS + 4498c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + StreamItems.RAW_CONTACT_ID + " IN (" + 4499c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "SELECT " + RawContacts._ID + 4500c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " FROM " + Tables.RAW_CONTACTS + 4501c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 4502c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 4503c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro rawContactsDataSetClause + "))", 4504c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro accountWithDataSetParams); 4505c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro db.execSQL( 4506c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "DELETE FROM " + Tables.STREAM_ITEMS + 4507c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + StreamItems.RAW_CONTACT_ID + " IN (" + 4508c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro "SELECT " + RawContacts._ID + 4509c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " FROM " + Tables.RAW_CONTACTS + 4510c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 4511c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 4512c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro rawContactsDataSetClause + ")", 4513c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro accountWithDataSetParams); 4514c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro db.execSQL( 4515e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.RAW_CONTACTS + 4516e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 451743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + " = ?" + 451843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactsDataSetClause, accountWithDataSetParams); 45195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4520e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 4521e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 452243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + Settings.ACCOUNT_TYPE + " = ?", accountParams); 45235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4524e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov "DELETE FROM " + Tables.ACCOUNTS + 4525e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + "=?" + 452643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + RawContacts.ACCOUNT_TYPE + "=?" + 452743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactsDataSetClause, accountWithDataSetParams); 45285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL( 4529d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov "DELETE FROM " + Tables.DIRECTORIES + 4530d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov " WHERE " + Directory.ACCOUNT_NAME + "=?" + 453143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND " + Directory.ACCOUNT_TYPE + "=?", accountParams); 45324458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov resetDirectoryCache(); 4533e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 4534e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov 453533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // Find all aggregated contacts that used to contain the raw contacts 453633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // we have just deleted and see if they are still referencing the deleted 4537e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov // names or photos. If so, fix up those contacts. 453833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov HashSet<Long> orphanContactIds = Sets.newHashSet(); 45395d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = db.rawQuery("SELECT " + Contacts._ID + 454033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " FROM " + Tables.CONTACTS + 454133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " WHERE (" + Contacts.NAME_RAW_CONTACT_ID + " NOT NULL AND " + 454269cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov Contacts.NAME_RAW_CONTACT_ID + " NOT IN " + 454369cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + RawContacts._ID + 454469cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + "))" + 454533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " OR (" + Contacts.PHOTO_ID + " NOT NULL AND " + 454633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Contacts.PHOTO_ID + " NOT IN " + 454769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + Data._ID + 454869cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.DATA + "))", null); 454933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov try { 455033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov while (cursor.moveToNext()) { 455133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov orphanContactIds.add(cursor.getLong(0)); 455233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 455333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } finally { 455433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov cursor.close(); 455533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 455633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 455733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov for (Long contactId : orphanContactIds) { 45585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateAggregateData(mTransactionContext.get(), contactId); 455933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 45605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().updateAllVisible(); 4561bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 456233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 456333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 456443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Now that we've done the account-based additions and subtractions from the Accounts 456543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // table, check for raw contacts that have been added with a data set and add Accounts 456643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // entries for those if necessary. 456743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro existingAccountsWithDataSets = findValidAccountsWithDataSets(Tables.ACCOUNTS); 456843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Set<AccountWithDataSet> rawContactAccountsWithDataSets = 456943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro findValidAccountsWithDataSets(Tables.RAW_CONTACTS); 457043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro rawContactAccountsWithDataSets.removeAll(existingAccountsWithDataSets); 457143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 457243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Any remaining raw contact sub-accounts need to be added to the Accounts table. 457343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro for (AccountWithDataSet accountWithDataSet : rawContactAccountsWithDataSets) { 457443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountsChanged = true; 457543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 457643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // Add an account entry to match the raw contact. 45775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 457843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ", " + RawContacts.ACCOUNT_TYPE + ", " + RawContacts.DATA_SET 457943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + ") VALUES (?, ?, ?)", 458043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new String[] { 458143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountName(), 458243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getAccountType(), 458343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountWithDataSet.getDataSet() 458443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro }); 458543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 458643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro 4587e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov if (accountsChanged) { 458843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // TODO: Should sync state take data set into consideration? 45895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getSyncState().onAccountsChanged(db, accounts); 4590e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 45915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.setTransactionSuccessful(); 459270d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 45935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.endTransaction(); 459470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 459573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.clear(); 45963826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 45973826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (accountsChanged) { 45983826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateContactsAccountCount(accounts); 45993826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateProviderStatus(); 46003826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46013826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 4602afb84050536a4472c13efc0e996d31132d254605Dmitri Plotnikov return accountsChanged; 460370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 4604619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 46053826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private void updateContactsAccountCount(Account[] accounts) { 46063826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov int count = 0; 46073826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov for (Account account : accounts) { 46083826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov if (isContactsAccount(account)) { 46093826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov count++; 46103826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46113826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46123826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mContactsAccountCount = count; 46133826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46143826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 46153826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov protected boolean isContactsAccount(Account account) { 46163826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov final IContentService cs = ContentResolver.getContentService(); 46173826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov try { 46183826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return cs.getIsSyncable(account, ContactsContract.AUTHORITY) > 0; 46193826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } catch (RemoteException e) { 46203826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov Log.e(TAG, "Cannot obtain sync flag for account: " + account, e); 46213826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return false; 46223826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46233826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 46243826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 462572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void onPackageChanged(String packageName) { 4626bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_DIRECTORIES, packageName); 4627d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4628d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4629619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 463043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * Finds all distinct account types and data sets present in the specified table. 4631627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov */ 463243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro private Set<AccountWithDataSet> findValidAccountsWithDataSets(String table) { 463343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Set<AccountWithDataSet> accountsWithDataSets = new HashSet<AccountWithDataSet>(); 46345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().rawQuery( 463543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro "SELECT DISTINCT " + RawContacts.ACCOUNT_NAME + "," + RawContacts.ACCOUNT_TYPE + 463643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro "," + RawContacts.DATA_SET + 463743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " FROM " + table, null); 4638627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 4639627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov while (c.moveToNext()) { 4640dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!c.isNull(0) || !c.isNull(1)) { 464143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountsWithDataSets.add( 464243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro new AccountWithDataSet(c.getString(0), c.getString(1), c.getString(2))); 4643627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4644627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4645627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } finally { 4646627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c.close(); 4647627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 464843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro return accountsWithDataSets; 4649627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4650627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 46514f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 46524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 46534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 465415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 465515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov waitForAccess(mReadAccessLatch); 465615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 46575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Query the profile DB if appropriate. 46585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 46595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 46605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileProvider.query(uri, projection, selection, selectionArgs, sortOrder); 46615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 46625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 46635d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Otherwise proceed with a normal query against the contacts DB. 46645d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 46655d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mContactsHelper.getReadableDatabase()); 4666d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String directory = getQueryParameter(uri, ContactsContract.DIRECTORY_PARAM_KEY); 4667385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov if (directory == null) { 46683716f1447ceb21180d1301790eabd8b9453f486dDave Santoro return wrapCursor(uri, 46695d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, -1)); 4670385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } else if (directory.equals("0")) { 46713716f1447ceb21180d1301790eabd8b9453f486dDave Santoro return wrapCursor(uri, 46723716f1447ceb21180d1301790eabd8b9453f486dDave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, 46735d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Directory.DEFAULT)); 4674d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } else if (directory.equals("1")) { 46753716f1447ceb21180d1301790eabd8b9453f486dDave Santoro return wrapCursor(uri, 46763716f1447ceb21180d1301790eabd8b9453f486dDave Santoro queryLocal(uri, projection, selection, selectionArgs, sortOrder, 46775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Directory.LOCAL_INVISIBLE)); 4678d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4679d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4680d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov DirectoryInfo directoryInfo = getDirectoryAuthority(directory); 4681d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo == null) { 4682a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov Log.e(TAG, "Invalid directory ID: " + uri); 4683a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov return null; 4684d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4685d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4686d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Builder builder = new Uri.Builder(); 4687d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.scheme(ContentResolver.SCHEME_CONTENT); 4688d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.authority(directoryInfo.authority); 4689d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.encodedPath(uri.getEncodedPath()); 4690d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountName != null) { 4691d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, directoryInfo.accountName); 4692d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4693d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (directoryInfo.accountType != null) { 4694d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, directoryInfo.accountType); 4695d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 46962e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 46972e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov String limit = getLimit(uri); 46982e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov if (limit != null) { 46992e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov builder.appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, limit); 47002e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov } 47012e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 4702d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Uri directoryUri = builder.build(); 470309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 470409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov if (projection == null) { 470509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov projection = getDefaultProjection(uri); 470609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 470709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 4708332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov Cursor cursor = getContext().getContentResolver().query(directoryUri, projection, selection, 4709d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov selectionArgs, sortOrder); 47106ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 47116ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (cursor == null) { 47126ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return null; 47136ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 47146ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 4715547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro CrossProcessCursor crossProcessCursor = getCrossProcessCursor(cursor); 4716547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro if (crossProcessCursor != null) { 4717547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro return wrapCursor(uri, cursor); 4718547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } else { 4719547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro return matrixCursorFromCursor(wrapCursor(uri, cursor)); 4720547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } 47213716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 47223716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 4723547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro private Cursor wrapCursor(Uri uri, Cursor cursor) { 4724547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro 4725547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro // If the cursor doesn't contain a snippet column, don't bother wrapping it. 4726547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro if (cursor.getColumnIndex(SearchSnippetColumns.SNIPPET) < 0) { 47275517770250b3afa4fd88b6869c3244680821d222Dave Santoro if (VERBOSE_LOGGING) { 47285517770250b3afa4fd88b6869c3244680821d222Dave Santoro return new InstrumentedCursorWrapper(cursor, uri, TAG); 47295517770250b3afa4fd88b6869c3244680821d222Dave Santoro } else { 47305517770250b3afa4fd88b6869c3244680821d222Dave Santoro return cursor; 47315517770250b3afa4fd88b6869c3244680821d222Dave Santoro } 4732547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } 4733547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro 47343716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Parse out snippet arguments for use when snippets are retrieved from the cursor. 47353716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String[] args = null; 47363716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String snippetArgs = 47373716f1447ceb21180d1301790eabd8b9453f486dDave Santoro getQueryParameter(uri, SearchSnippetColumns.SNIPPET_ARGS_PARAM_KEY); 47383716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (snippetArgs != null) { 47393716f1447ceb21180d1301790eabd8b9453f486dDave Santoro args = snippetArgs.split(","); 47403716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 47413716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 47423716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String query = uri.getLastPathSegment(); 47433716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String startMatch = args != null && args.length > 0 ? args[0] 47443716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_START_MATCH; 47453716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String endMatch = args != null && args.length > 1 ? args[1] 47463716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_END_MATCH; 47473716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String ellipsis = args != null && args.length > 2 ? args[2] 47483716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_ELLIPSIS; 47493716f1447ceb21180d1301790eabd8b9453f486dDave Santoro int maxTokens = args != null && args.length > 3 ? Integer.parseInt(args[3]) 47503716f1447ceb21180d1301790eabd8b9453f486dDave Santoro : DEFAULT_SNIPPET_ARG_MAX_TOKENS; 47513716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 47525517770250b3afa4fd88b6869c3244680821d222Dave Santoro if (VERBOSE_LOGGING) { 47535517770250b3afa4fd88b6869c3244680821d222Dave Santoro return new InstrumentedCursorWrapper(new SnippetizingCursorWrapper( 47545517770250b3afa4fd88b6869c3244680821d222Dave Santoro cursor, query, startMatch, endMatch, ellipsis, maxTokens), uri, TAG); 47555517770250b3afa4fd88b6869c3244680821d222Dave Santoro } else { 47565517770250b3afa4fd88b6869c3244680821d222Dave Santoro return new SnippetizingCursorWrapper(cursor, query, startMatch, endMatch, ellipsis, 47575517770250b3afa4fd88b6869c3244680821d222Dave Santoro maxTokens); 47585517770250b3afa4fd88b6869c3244680821d222Dave Santoro } 47596ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 47606ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 47616ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov private CrossProcessCursor getCrossProcessCursor(Cursor cursor) { 47626ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov Cursor c = cursor; 47636ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (c instanceof CrossProcessCursor) { 47646ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return (CrossProcessCursor) c; 47656ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } else if (c instanceof CursorWindow) { 47666ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return getCrossProcessCursor(((CursorWrapper) c).getWrappedCursor()); 47676ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } else { 47686ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return null; 47696ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 47706ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 47716ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 47726ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov public MatrixCursor matrixCursorFromCursor(Cursor cursor) { 47736ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov MatrixCursor newCursor = new MatrixCursor(cursor.getColumnNames()); 47746ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov int numColumns = cursor.getColumnCount(); 47756ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov String data[] = new String[numColumns]; 47766ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov cursor.moveToPosition(-1); 47776ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov while (cursor.moveToNext()) { 47786ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov for (int i = 0; i < numColumns; i++) { 47796ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov data[i] = cursor.getString(i); 47806ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 47816ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov newCursor.addRow(data); 4782332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov } 47836ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return newCursor; 4784d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4785d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4786d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private static final class DirectoryQuery { 4787d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 4788d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory._ID, 4789d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.DIRECTORY_AUTHORITY, 4790d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_NAME, 4791d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Directory.ACCOUNT_TYPE 4792d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov }; 4793d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4794d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int DIRECTORY_ID = 0; 4795d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int AUTHORITY = 1; 4796d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_NAME = 2; 4797d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov public static final int ACCOUNT_TYPE = 3; 4798d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4799d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 4800d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov /** 4801d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov * Reads and caches directory information for the database. 4802d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov */ 4803d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private DirectoryInfo getDirectoryAuthority(String directoryId) { 48044458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov synchronized (mDirectoryCache) { 48054458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov if (!mDirectoryCacheValid) { 48064458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCache.clear(); 48075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = mDbHelper.get().getReadableDatabase(); 480849d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov Cursor cursor = db.query(Tables.DIRECTORIES, 48094458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DirectoryQuery.COLUMNS, 48104458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov null, null, null, null, null); 48114458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov try { 48124458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov while (cursor.moveToNext()) { 48134458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DirectoryInfo info = new DirectoryInfo(); 48144458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov String id = cursor.getString(DirectoryQuery.DIRECTORY_ID); 48154458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.authority = cursor.getString(DirectoryQuery.AUTHORITY); 48164458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.accountName = cursor.getString(DirectoryQuery.ACCOUNT_NAME); 48174458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov info.accountType = cursor.getString(DirectoryQuery.ACCOUNT_TYPE); 48184458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCache.put(id, info); 48194458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 48204458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } finally { 48214458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov cursor.close(); 4822d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 48234458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCacheValid = true; 4824d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4825d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 48264458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov return mDirectoryCache.get(directoryId); 48274458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 4828d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4829d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 483072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov public void resetDirectoryCache() { 48314458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov synchronized(mDirectoryCache) { 48324458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov mDirectoryCacheValid = false; 48334458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 483472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov } 483572e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 48365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro protected Cursor queryLocal(Uri uri, String[] projection, String selection, 48375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String[] selectionArgs, String sortOrder, long directoryId) { 4838bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 4839bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 4840bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 48410b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 48425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 48435d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 48445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 48455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 484635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4847d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 48481f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 4849c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 4850c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 48512ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // The expression used in bundleLetterCountExtras() to get count. 48522ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki String addressBookIndexerCountExpression = null; 48532ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 4854a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 48554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 485635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 48575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_SYNCSTATE: 48585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mDbHelper.get().getSyncState().query(mActiveDb.get(), projection, selection, 48595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selectionArgs, sortOrder); 486035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4861d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 4862763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 48634b64b6e8f448938434cb1e022a4e7dfaae8f9c8cMakoto Onuki appendLocalDirectorySelectionIfNeeded(qb, directoryId); 4864619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 4865619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4866619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4867d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 48684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 4869763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 48704da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 48714da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 48726bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 48736bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 48746bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 48755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 48765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 48775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 48785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 48795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 48805d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 4881fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 48825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 4883a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 48845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 48855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 48865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 48875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 4888763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 4889a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 48905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 4891a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 4892a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey); 4893a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 48945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 48955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 48965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 48975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4898763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 48994da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 49005d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String.valueOf(lookupContactIdByLookupKey(mActiveDb.get(), lookupKey))); 49014da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 49025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 49035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 49045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 49052149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov case CONTACTS_LOOKUP_DATA: 49062149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov case CONTACTS_LOOKUP_ID_DATA: { 49072149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 49082149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov int segmentCount = pathSegments.size(); 49092149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount < 4) { 49105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 49112149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov "Missing a lookup key", uri)); 49122149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 49132149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov String lookupKey = pathSegments.get(2); 49142149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (segmentCount == 5) { 49152149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 49162149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 49172149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(lookupQb, uri, projection, false); 4918a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 49195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 4920a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 4921a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.CONTACT_ID, contactId, Data.LOOKUP_KEY, lookupKey); 4922a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 49232149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov return c; 49242149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 49252149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 49262149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov // TODO see if the contact exists but has no data rows (rare) 49272149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 49282149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 49292149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 49305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 49312149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 493224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro String.valueOf(contactId)); 49332149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov qb.appendWhere(" AND " + Data.CONTACT_ID + "=?"); 49342149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov break; 49352149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 49362149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 49373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_ID_STREAM_ITEMS: { 49383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long contactId = Long.parseLong(uri.getPathSegments().get(1)); 49393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 49403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 4941af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann qb.appendWhere(StreamItems.CONTACT_ID + "=?"); 49423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 49433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 49443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 49453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_LOOKUP_STREAM_ITEMS: 49463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case CONTACTS_LOOKUP_ID_STREAM_ITEMS: { 49473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann List<String> pathSegments = uri.getPathSegments(); 49483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann int segmentCount = pathSegments.size(); 49493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (segmentCount < 4) { 49505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 49513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann "Missing a lookup key", uri)); 49523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 49533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String lookupKey = pathSegments.get(2); 49543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (segmentCount == 5) { 49553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long contactId = Long.parseLong(pathSegments.get(3)); 49563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 49573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(lookupQb); 49585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 49593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann projection, selection, selectionArgs, sortOrder, groupBy, limit, 4960af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann StreamItems.CONTACT_ID, contactId, 4961af10329f85c5d8c4196c495a9f0f9a6c6ecbc231Daniel Lehmann StreamItems.CONTACT_LOOKUP_KEY, lookupKey); 49623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann if (c != null) { 49633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return c; 49643b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 49653b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 49663b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 49673b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 49685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 49693b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 49703b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(RawContacts.CONTACT_ID + "=?"); 49713b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 49723b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 49733b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 4974f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 497542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 49765d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 4977ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 4978f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 49794da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 498024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro String.valueOf(contactId)); 49814da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 4982f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 4983f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 4984f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 498542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 498642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); 498742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann String currentDateString = dateFormat.format(new Date()).toString(); 49885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mActiveDb.get().rawQuery( 498942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann "SELECT" + 499042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " 'vcards_' || ? || '.vcf' AS " + OpenableColumns.DISPLAY_NAME + "," + 499142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " NULL AS " + OpenableColumns.SIZE, 499242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann new String[] { currentDateString }); 499342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 499442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 4995ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 4996916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String filterParam = ""; 4997ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 4998916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov filterParam = uri.getLastPathSegment(); 4999ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 50007ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov setTablesAndProjectionMapForContactsWithSnippet( 50017ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov qb, uri, projection, filterParam, directoryId); 5002ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5003ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5004ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 5005ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 5006ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 50072f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Basically the resultant SQL should look like this: 50082f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // (SQL for listing starred items) 50092f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // UNION ALL 50102f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // (SQL for listing frequently contacted items) 50112f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // ORDER BY ... 50122f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 50132f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final boolean phoneOnly = readBooleanQueryParameter( 50142f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa uri, ContactsContract.STREQUENT_PHONE_ONLY, false); 50152f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (match == CONTACTS_STREQUENT_FILTER && uri.getPathSegments().size() > 3) { 50164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 50174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5018e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 50195e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 50202f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa selection = DbQueryUtils.concatenateClauses(selection, sb.toString()); 50214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 50224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 50232f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa String[] subProjection = null; 50245e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 50252f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa subProjection = appendProjectionArg(projection, TIMES_USED_SORT_COLUMN); 50265e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 50275e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 50284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 50294928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, false); 50304928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setProjectionMap(phoneOnly ? 50314928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa sStrequentPhoneOnlyStarredProjectionMap 50324928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa : sStrequentStarredProjectionMap); 50339dbfd650ccf93714f3266e80f9fbdbcb526ae7b3Daisuke Miyakawa if (phoneOnly) { 50345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro qb.appendWhere(DbQueryUtils.concatenateClauses( 50355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro selection, Contacts.HAS_PHONE_NUMBER + "=1")); 50369dbfd650ccf93714f3266e80f9fbdbcb526ae7b3Daisuke Miyakawa } 50372f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.setStrict(true); 50382f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final String starredQuery = qb.buildQuery(subProjection, 503924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Contacts.STARRED + "=1", Contacts._ID, null, null, null); 5040d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 50412f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Reset the builder. 5042d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 50432f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.setStrict(true); 50444928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 50454928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // Build the second query for frequent part. 50464928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa final String frequentQuery; 50474928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa if (phoneOnly) { 50484928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa final StringBuilder tableBuilder = new StringBuilder(); 50494928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // In phone only mode, we need to look at view_data instead of 50504928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // contacts/raw_contacts to obtain actual phone numbers. One problem is that 50514928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // view_data is much larger than view_contacts, so our query might become much 50524928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // slower. 50534928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // 50544928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // To avoid the possible slow down, we start from data usage table and join 50554928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // view_data to the table, assuming data usage table is quite smaller than 50564928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // data rows (almost always it should be), and we don't want any phone 50574928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // numbers not used by the user. This way sqlite is able to drop a number of 50584928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa // rows in view_data in the early stage of data lookup. 50594928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa tableBuilder.append(Tables.DATA_USAGE_STAT 50604928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + " INNER JOIN " + Views.DATA + " " + Tables.DATA 50614928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + " ON (" + DataUsageStatColumns.CONCRETE_DATA_ID + "=" 50624928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + DataColumns.CONCRETE_ID + " AND " 50634928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + DataUsageStatColumns.CONCRETE_USAGE_TYPE + "=" 50644928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + DataUsageStatColumns.USAGE_TYPE_INT_CALL + ")"); 50654928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa appendContactPresenceJoin(tableBuilder, projection, RawContacts.CONTACT_ID); 50664928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa appendContactStatusUpdateJoin(tableBuilder, projection, 50674928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa ContactsColumns.LAST_STATUS_UPDATE_ID); 50684928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa 50694928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setTables(tableBuilder.toString()); 50704928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setProjectionMap(sStrequentPhoneOnlyFrequentProjectionMap); 50714928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.appendWhere(DbQueryUtils.concatenateClauses( 50724928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa selection, 50734928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa Contacts.STARRED + "=0 OR " + Contacts.STARRED + " IS NULL", 50744928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa MimetypesColumns.MIMETYPE + " IN (" 50754928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + "'" + Phone.CONTENT_ITEM_TYPE + "', " 50764928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa + "'" + SipAddress.CONTENT_ITEM_TYPE + "')")); 50774928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa frequentQuery = qb.buildQuery(subProjection, null, null, null, null, null); 50784928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa } else { 50794928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, true); 50804928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.setProjectionMap(sStrequentFrequentProjectionMap); 50814928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa qb.appendWhere(DbQueryUtils.concatenateClauses( 50824928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa selection, 50835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro "(" + Contacts.STARRED + " =0 OR " + Contacts.STARRED + " IS NULL)")); 50844928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa frequentQuery = qb.buildQuery(subProjection, 50854928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa null, Contacts._ID, null, null, null); 50864928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa } 5087d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 5088d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 50892f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final String unionQuery = 50902f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 50912f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa STREQUENT_ORDER_BY, STREQUENT_LIMIT); 50922f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 50932f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Here, we need to use selection / selectionArgs (supplied from users) "twice", 50942f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // as we want them both for starred items and for frequently contacted items. 50952f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // 50962f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // e.g. if the user specify selection = "starred =?" and selectionArgs = "0", 50972f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // the resultant SQL should be like: 50982f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // SELECT ... WHERE starred =? AND ... 50992f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // UNION ALL 51002f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // SELECT ... WHERE starred =? AND ... 51012f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa String[] doubledSelectionArgs = null; 51022f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (selectionArgs != null) { 51032f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa final int length = selectionArgs.length; 51042f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa doubledSelectionArgs = new String[length * 2]; 51057d7d0e95636344c01eb4e4d034791c199bee98e9Daisuke Miyakawa System.arraycopy(selectionArgs, 0, doubledSelectionArgs, 0, length); 51067d7d0e95636344c01eb4e4d034791c199bee98e9Daisuke Miyakawa System.arraycopy(selectionArgs, 0, doubledSelectionArgs, length, length); 51072f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 51082f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 51095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = mActiveDb.get().rawQuery(unionQuery, doubledSelectionArgs); 51102f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa if (cursor != null) { 51112f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa cursor.setNotificationUri(getContext().getContentResolver(), 5112d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 5113d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 51142f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa return cursor; 5115d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 5116d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 511745ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa case CONTACTS_FREQUENT: { 511845ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, true); 511945ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa qb.setProjectionMap(sStrequentFrequentProjectionMap); 512045ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa groupBy = Contacts._ID; 512145ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa if (!TextUtils.isEmpty(sortOrder)) { 512245ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa sortOrder = FREQUENT_ORDER_BY + ", " + sortOrder; 512345ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa } else { 512445ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa sortOrder = FREQUENT_ORDER_BY; 512545ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa } 512645ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa break; 512745ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa } 512845ae7eaf0e2c9459ccbeeb5eb5977f055c4ed8ecDaisuke Miyakawa 5129ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 5130763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 5131b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 513271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 51334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 5134b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5135b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 5136b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5137b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 513824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: { 513924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForContacts(qb, uri, projection); 514024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 514124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 514224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 514324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_ENTITIES: { 514424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForEntities(qb, uri, projection); 514524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 514624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 514724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 514824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_DATA: { 514924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForData(qb, uri, projection, false); 515024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 515124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 515224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 515324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_DATA_ID: { 515424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForData(qb, uri, projection, false); 515524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 51565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro qb.appendWhere(" AND " + Data._ID + "=?"); 515724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 515824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 515924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 516024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: { 5161ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 516224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro qb.setProjectionMap(sContactsVCardProjectionMap); 516324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 516424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 516524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 5166a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_DATA: { 51674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 516882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 51694da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 51704da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 51716bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 51726bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 517300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 5174a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 51753653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 517682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 51774da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 51784da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 51793653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 51803653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 51813653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 51823653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 5183a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_ENTITIES: { 5184a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 5185a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 5186a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 5187a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 5188a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 5189a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5190a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5191a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ENTITIES: 5192a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_LOOKUP_ID_ENTITIES: { 5193a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 5194a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov int segmentCount = pathSegments.size(); 5195a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount < 4) { 51965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 5197a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov "Missing a lookup key", uri)); 5198a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5199a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lookupKey = pathSegments.get(2); 5200a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (segmentCount == 5) { 5201a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 5202a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 5203a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(lookupQb, uri, projection); 5204a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(" AND "); 5205a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 52065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 5207a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov projection, selection, selectionArgs, sortOrder, groupBy, limit, 5208a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.CONTACT_ID, contactId, 5209a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.Entity.LOOKUP_KEY, lookupKey); 5210a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 5211a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 5212a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5213a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5214a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5215a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForEntities(qb, uri, projection); 5216a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 52175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String.valueOf(lookupContactIdByLookupKey(mActiveDb.get(), lookupKey))); 5218a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + Contacts.Entity.CONTACT_ID + "=?"); 5219a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 5220a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5221a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 52223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS: { 52233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 52243b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 52253b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 52263b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 52273b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID: { 52283b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 52293b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 52309b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann qb.appendWhere(StreamItems._ID + "=?"); 52313b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 52323b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 52333b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 52343b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_LIMIT: { 52356802030a777c0c3ba1dc029c534cca4784260632Dave Santoro MatrixCursor cursor = new MatrixCursor(new String[]{StreamItems.MAX_ITEMS}, 1); 52366802030a777c0c3ba1dc029c534cca4784260632Dave Santoro cursor.addRow(new Object[]{MAX_STREAM_ITEMS_PER_RAW_CONTACT}); 52373b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann return cursor; 52383b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 52393b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 52403b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_PHOTOS: { 52413b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 52423b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 52433b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 52443b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 52453b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS: { 52463b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 52473b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 52483b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemId); 52493b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=?"); 52503b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 52513b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 52523b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 52533b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case STREAM_ITEMS_ID_PHOTOS_ID: { 52543b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItemPhotos(qb); 52553b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemId = uri.getPathSegments().get(1); 52563b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann String streamItemPhotoId = uri.getPathSegments().get(3); 52573b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemPhotoId); 52583b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, streamItemId); 52593b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=? AND " + 52603b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann StreamItemPhotosColumns.CONCRETE_ID + "=?"); 52613b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 52623b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 52633b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 5264f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case PHOTO_DIMENSIONS: { 5265f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro MatrixCursor cursor = new MatrixCursor( 5266f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro new String[]{DisplayPhoto.DISPLAY_MAX_DIM, DisplayPhoto.THUMBNAIL_MAX_DIM}, 5267f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 1); 5268f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro cursor.addRow(new Object[]{mMaxDisplayPhotoDim, mMaxThumbnailPhotoDim}); 5269f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return cursor; 5270f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 5271f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 52724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 527382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 527489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 52752ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 52762ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // Dedupe phone numbers per contact. 5277cf55cbe8932f620484a3634d13ecc116c32fdc99Daisuke Miyakawa groupBy = RawContacts.CONTACT_ID + ", " + Data.DATA1; 52782ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 52792ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // In this case, because we dedupe phone numbers, the address book indexer needs 52802ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // to take it into account too. (Otherwise headers will appear in wrong positions.) 52812ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // So use count(distinct pair(CONTACT_ID, PHONE NUMBER)) instead of count(*). 52822ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // But because there's no such thing as pair() on sqlite, we use 52832ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // CONTACT_ID || ',' || PHONE NUMBER instead. 52842ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // This only slows down the query by 14% with 10,000 contacts. 52852ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki addressBookIndexerCountExpression = "DISTINCT " 52862ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki + RawContacts.CONTACT_ID + "||','||" + Data.DATA1; 52872815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 52882815f58f72f109790585931f601a63ddc02536a5Evan Millar } 52892815f58f72f109790585931f601a63ddc02536a5Evan Millar 529048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 529182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 52924da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 529348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 52944da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 529548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 529648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 529748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 5298ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 529946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String typeParam = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 530046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Integer typeInt = sDataUsageTypeMap.get(typeParam); 530146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (typeInt == null) { 530246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa typeInt = DataUsageStatColumns.USAGE_TYPE_INT_CALL; 530346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 530446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, true, typeInt); 530589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 5306ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 53074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 53084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5309a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 53105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 531145d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov boolean hasCondition = false; 53125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 53135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 53145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 5315155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN " + 5316155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov "(SELECT " + RawContactsColumns.CONCRETE_ID + 5317155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.SEARCH_INDEX + 5318155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 5319155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " ON (" + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID 5320155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov + "=" + RawContactsColumns.CONCRETE_CONTACT_ID + ")" + 5321155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " WHERE " + SearchIndexColumns.NAME + " MATCH "); 53222352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, sanitizeMatch(filterParam) + "*"); 5323155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(")"); 53245e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 532545d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 53265e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 53275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 5328892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String number = PhoneNumberUtils.normalizeNumber(filterParam); 5329892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (!TextUtils.isEmpty(number)) { 53305e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 53315e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 53325e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 53335e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 5334892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov " IN (SELECT DISTINCT " + PhoneLookupColumns.DATA_ID 5335892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 5336892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 5337892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append(number); 5338892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append("%')"); 533945d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 534045d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov } 534145d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov 534245d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov if (!hasCondition) { 534345d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // If it is neither a phone number nor a name, the query should return 534445d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // an empty cursor. Let's ensure that. 534545d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov sb.append("0"); 53465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 53475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 5348a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 5349ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 535058567abca253f1efa2db5c39e17e42dca589e916Daisuke Miyakawa groupBy = "(CASE WHEN " + PhoneColumns.NORMALIZED_NUMBER 535158567abca253f1efa2db5c39e17e42dca589e916Daisuke Miyakawa + " IS NOT NULL THEN " + PhoneColumns.NORMALIZED_NUMBER 535258567abca253f1efa2db5c39e17e42dca589e916Daisuke Miyakawa + " ELSE " + Phone.NUMBER + " END), " + RawContacts.CONTACT_ID; 5353a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 535446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String accountPromotionSortOrder = getAccountPromotionSortOrder(uri); 535546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(accountPromotionSortOrder)) { 535646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = accountPromotionSortOrder + ", " + PHONE_FILTER_SORT_ORDER; 535746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 535846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sortOrder = PHONE_FILTER_SORT_ORDER; 535946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 5360a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 5361ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5362ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5363ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 53644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 536582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 536689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 53674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 53684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 53694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 537048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 537182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 53724da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 53734da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'" 53744da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + Data._ID + "=?"); 537548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 537648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 537748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 53785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 537982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 538089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 53814a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 538208768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String email = uri.getLastPathSegment(); 53835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String address = mDbHelper.get().extractAddressFromEmailAddress(email); 538408768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, address); 538508768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov qb.appendWhere(" AND UPPER(" + Email.DATA + ")=UPPER(?)"); 53864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 5387ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5388ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5389ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 53905e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 539146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String typeParam = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 539246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Integer typeInt = sDataUsageTypeMap.get(typeParam); 539346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (typeInt == null) { 539446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa typeInt = DataUsageStatColumns.USAGE_TYPE_INT_LONG_TEXT; 539546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 539646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, true, typeInt); 539707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov String filterParam = null; 53987d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa 539907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 540007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = uri.getLastPathSegment(); 540107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (TextUtils.isEmpty(filterParam)) { 540207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = null; 540307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 540407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 54055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 540607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterParam == null) { 540707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // If the filter is unspecified, return nothing 540807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(" AND 0"); 540907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } else { 541007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 541107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append(" AND " + Data._ID + " IN ("); 541207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 541307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov "SELECT " + Data._ID + 541407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 54152a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "="); 54165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro sb.append(mDbHelper.get().getMimeTypeIdForEmail()); 54172a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov sb.append(" AND " + Data.DATA1 + " LIKE "); 541807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, filterParam + '%'); 541920938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 5420155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append( 5421155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " UNION SELECT " + Data._ID + 5422155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.DATA + 5423155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " WHERE +" + DataColumns.MIMETYPE_ID + "="); 54245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro sb.append(mDbHelper.get().getMimeTypeIdForEmail()); 5425155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(" AND " + Data.RAW_CONTACT_ID + " IN " + 5426155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov "(SELECT " + RawContactsColumns.CONCRETE_ID + 5427155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " FROM " + Tables.SEARCH_INDEX + 5428155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 5429155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " ON (" + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID 5430155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov + "=" + RawContactsColumns.CONCRETE_CONTACT_ID + ")" + 5431155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov " WHERE " + SearchIndexColumns.NAME + " MATCH "); 54322352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, sanitizeMatch(filterParam) + "*"); 5433155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov sb.append(")"); 54345e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 5436a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 54375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54385e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + 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 + ", " + EMAIL_FILTER_SORT_ORDER; 54437d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa } else { 54447d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa sortOrder = EMAIL_FILTER_SORT_ORDER; 54457d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa } 5446a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 54475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 54485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 54495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 5450ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 545182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 545289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 545389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 5454ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 5455ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5456ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 545748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 545882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 54594da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 546048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 546148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 54624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 546348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 546448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 546548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 54665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 5467763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 54684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 54694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 54704f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 54715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 54725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 5473763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 54744da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 54754da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 54764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 54774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 54784f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 54795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 54805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 548182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 54824da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 54834da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 548424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 548524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 548624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 54873b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann case RAW_CONTACTS_ID_STREAM_ITEMS: { 54883b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 54893b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann setTablesAndProjectionMapForStreamItems(qb); 54903b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 54913b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.appendWhere(StreamItems.RAW_CONTACT_ID + "=?"); 54923b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann break; 54933b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 549424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 549582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro case RAW_CONTACTS_ID_STREAM_ITEMS_ID: { 549682780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 549782780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro long streamItemId = Long.parseLong(uri.getPathSegments().get(3)); 549882780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro setTablesAndProjectionMapForStreamItems(qb); 549982780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(streamItemId)); 5500c88cc79e0e19b8299a2a356c7d70b48f70b4a93eDave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 550182780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro qb.appendWhere(StreamItems.RAW_CONTACT_ID + "=? AND " + 550282780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro StreamItems._ID + "=?"); 550382780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro break; 550482780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro } 550582780691f1a3b4d8784e29a961b1140cd07bc9a8Dave Santoro 550624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS: { 550724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForRawContacts(qb, uri); 550824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 550924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 551024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 551124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID: { 551224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long rawContactId = ContentUris.parseId(uri); 551324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 551424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForRawContacts(qb, uri); 55155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro qb.appendWhere(" AND " + RawContacts._ID + "=?"); 551624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 551724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 551824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 551924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID_DATA: { 552024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(2)); 552124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 552224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForData(qb, uri, projection, false); 55235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 552424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro break; 552524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 552624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 552724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID_ENTITIES: { 552824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(2)); 552924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 553024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro setTablesAndProjectionMapForRawEntities(qb, uri); 55315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro qb.appendWhere(" AND " + RawContacts._ID + "=?"); 5532e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 5533e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 5534e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 5535e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 553682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 5537e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 5538e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 5539e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 55404f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 554124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long dataId = ContentUris.parseId(uri); 554282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 55434da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 55444da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 5545a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 5546a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 5547a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 5548a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 55494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5550a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 5551a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 5552a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 5553892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sortOrder = " length(lookup.normalized_number) DESC"; 5554a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 5555a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 5556e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 5557e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov String numberE164 = PhoneNumberUtils.formatNumberToE164(number, 55585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getCurrentCountryIso()); 5559892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov String normalizedNumber = 5560892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov PhoneNumberUtils.normalizeNumber(number); 55615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().buildPhoneLookupAndContactQuery(qb, normalizedNumber, numberE164); 5562e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 5563e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 5564e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 5565e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 5566a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 5567a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 5568a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 5569ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 5570ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.GROUPS); 5571ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 557243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro appendAccountFromParameter(qb, uri, true); 5573ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 5574ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 5575ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5576ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 5577ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.GROUPS); 5578ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 55794da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 55804da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Groups._ID + "=?"); 5581ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 5582ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 5583ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5584ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 5585f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa final boolean returnGroupCountPerAccount = 5586f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa readBooleanQueryParameter(uri, Groups.PARAM_RETURN_GROUP_COUNT_PER_ACCOUNT, 5587f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa false); 5588f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa qb.setTables(Views.GROUPS + " AS " + Tables.GROUPS); 5589f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa qb.setProjectionMap(returnGroupCountPerAccount ? 5590f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa sGroupsSummaryProjectionMapWithGroupCountPerAccount 5591f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa : sGroupsSummaryProjectionMap); 559243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro appendAccountFromParameter(qb, uri, true); 5593f1efadb1255fd75305b59802f736905b9d66e449Daisuke Miyakawa groupBy = GroupsColumns.CONCRETE_ID; 5594ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 5595ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 5596ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5597b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 55980c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 5599b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 5600b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 5601b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 5602b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 560331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 5604d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 56052d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 56062d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 56072d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 56082d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 560931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 5610d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 5611d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 561231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 561331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 561431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 561531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 56165b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ArrayList<AggregationSuggestionParameter> parameters = null; 56175b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov List<String> query = uri.getQueryParameters("query"); 56185b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov if (query != null && !query.isEmpty()) { 56195b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters = new ArrayList<AggregationSuggestionParameter>(query.size()); 56205b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov for (String parameter : query) { 56215b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov int offset = parameter.indexOf(':'); 56225b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameters.add(offset == -1 56235b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov ? new AggregationSuggestionParameter( 562476dfa406e2cde19c824983c37fc92c1c5bf63eecDaniel Lehmann AggregationSuggestions.PARAMETER_MATCH_NAME, 56255b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter) 56265b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov : new AggregationSuggestionParameter( 56275b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(0, offset), 56285b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov parameter.substring(offset + 1))); 56295b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 56305b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 56315b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 5632763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 56337581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 56345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mAggregator.get().queryAggregationSuggestions(qb, projection, contactId, 56355b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov maxSuggestions, filter, parameters); 563631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 563731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 5638eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 5639eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 5640eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 564143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro appendAccountFromParameter(qb, uri, false); 5642e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 5643e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 5644e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 56455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final String groupMembershipMimetypeId = Long.toString(mDbHelper.get() 5646e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 564782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 56485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().isInProjection(projection, Settings.UNGROUPED_COUNT)) { 5649e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 5650e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 565182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 56525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().isInProjection( 56535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro projection, Settings.UNGROUPED_WITH_PHONES)) { 5654e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 5655e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 5656e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 5657eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 5658eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 5659eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 56605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case STATUS_UPDATES: 56615d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro case PROFILE_STATUS_UPDATES: { 56620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 56635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 56645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 56655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 566682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 56670a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 56684da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 56694da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=?"); 56705ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 56715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 56725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 5673c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 5674174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery( 56755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get(), uri, projection, limit); 5676c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5677c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 5678c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 56792d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill String lookupKey = uri.getLastPathSegment(); 5680174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String filter = getQueryParameter( 5681174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov uri, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA); 5682174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return mGlobalSearchSupport.handleSearchShortcutRefresh( 56835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get(), projection, lookupKey, filter); 5684c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5685c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 56861b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 5687ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 56881b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 56891b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 56901b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 56911b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 5692ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 56931b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 56941b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 56951b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 56961b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 56971b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 5698ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 56991b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 57001b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 57011b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 57021b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 57031b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 5704ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.CONTACTS); 57051b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 570671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 57071b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 57081b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 57091b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 571046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITIES: { 5711a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 571246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 571346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 571446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 571546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 571646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 5717a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawEntities(qb, uri); 57184da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 57194da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 572046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 572146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 572246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 572309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov case PROVIDER_STATUS: { 572409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return queryProviderStatus(uri, projection); 572509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 572609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 5727d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES : { 5728d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 5729d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 5730d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 5731d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 5732d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 5733d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID : { 5734385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov long id = ContentUris.parseId(uri); 5735d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setTables(Tables.DIRECTORIES); 5736d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.setProjectionMap(sDirectoryProjectionMap); 5737385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(id)); 5738d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov qb.appendWhere(Directory._ID + "=?"); 5739d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 5740d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 5741d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 57427a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov case COMPLETE_NAME: { 57437a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return completeName(uri, projection); 57447a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 57457a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 57464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 5747f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 5748c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 57494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 57504f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 575109e69522745551522c55dff27424496f255def46Daniel Lehmann qb.setStrict(true); 57527f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov 5753ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov Cursor cursor = 57545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro query(mActiveDb.get(), qb, projection, selection, selectionArgs, sortOrder, groupBy, 57555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro limit); 5756ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (readBooleanQueryParameter(uri, ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, false)) { 57575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro cursor = bundleLetterCountExtras(cursor, mActiveDb.get(), qb, selection, 57582ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki selectionArgs, sortOrder, addressBookIndexerCountExpression); 5759ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5760ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return cursor; 57615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 57625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 57635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 57645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 57655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 5766038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 5767038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 5768038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 5769038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 57705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 57715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 57724f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 57734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 57744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 57754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 57764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 57774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 577809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov /** 577909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov * Creates a single-row cursor containing the current status of the provider. 578009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov */ 578109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private Cursor queryProviderStatus(Uri uri, String[] projection) { 578209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 578309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov RowBuilder row = cursor.newRow(); 578409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov for (int i = 0; i < projection.length; i++) { 578509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov if (ProviderStatus.STATUS.equals(projection[i])) { 578609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mProviderStatus); 578709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } else if (ProviderStatus.DATA1.equals(projection[i])) { 578809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mEstimatedStorageRequirement); 578909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 579009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 579109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return cursor; 579209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 579309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 5794a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** 5795a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * Runs the query with the supplied contact ID and lookup ID. If the query succeeds, 5796a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * it returns the resulting cursor, otherwise it returns null and the calling 5797a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * method needs to resolve the lookup key and rerun the query. 5798a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov */ 5799a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private Cursor queryWithContactIdAndLookupKey(SQLiteQueryBuilder lookupQb, 5800a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteDatabase db, Uri uri, 5801a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection, String selection, String[] selectionArgs, 5802a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String sortOrder, String groupBy, String limit, 5803a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn, long contactId, String lookupKeyColumn, String lookupKey) { 5804a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] args; 5805a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (selectionArgs == null) { 5806a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[2]; 5807a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } else { 5808a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args = new String[selectionArgs.length + 2]; 5809a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 5810a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5811a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[0] = String.valueOf(contactId); 5812a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov args[1] = Uri.encode(lookupKey); 5813a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov lookupQb.appendWhere(contactIdColumn + "=? AND " + lookupKeyColumn + "=?"); 5814a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, args, sortOrder, 5815a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov groupBy, limit); 5816a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c.getCount() != 0) { 5817a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return c; 5818a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 5819a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 5820a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov c.close(); 5821a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return null; 5822a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 582309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 5824bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov private static final class AddressBookIndexQuery { 5825bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String LETTER = "letter"; 5826bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String TITLE = "title"; 5827bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String COUNT = "count"; 5828ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5829bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String[] COLUMNS = new String[] { 5830bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov LETTER, TITLE, COUNT 5831ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 5832ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5833bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_LETTER = 0; 5834bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_TITLE = 1; 5835bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_COUNT = 2; 5836bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 58375d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // The first letter of the sort key column is what is used for the index headings. 58385d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public static final String SECTION_HEADING = "SUBSTR(%1$s,1,1)"; 583924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 5840de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa public static final String ORDER_BY = LETTER + " COLLATE " + PHONEBOOK_COLLATOR_NAME; 5841ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5842ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5843ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov /** 5844ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * Computes counts by the address book index titles and adds the resulting tally 5845ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * to the returned cursor as a bundle of extras. 5846ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov */ 5847ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov private Cursor bundleLetterCountExtras(Cursor cursor, final SQLiteDatabase db, 58482ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki SQLiteQueryBuilder qb, String selection, String[] selectionArgs, String sortOrder, 58492ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki String countExpression) { 5850409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki if (!(cursor instanceof AbstractCursor)) { 5851409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki Log.w(TAG, "Unable to bundle extras. Cursor is not AbstractCursor."); 5852409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki return cursor; 5853409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki } 5854ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortKey; 5855ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5856ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // The sort order suffix could be something like "DESC". 5857ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // We want to preserve it in the query even though we will change 5858ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // the sort column itself. 5859ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortOrderSuffix = ""; 5860ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (sortOrder != null) { 5861ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int spaceIndex = sortOrder.indexOf(' '); 5862ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (spaceIndex != -1) { 5863ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder.substring(0, spaceIndex); 5864ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortOrderSuffix = sortOrder.substring(spaceIndex); 5865ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 5866ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder; 5867ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5868ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 5869ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = Contacts.SORT_KEY_PRIMARY; 5870ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5871ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5872bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String locale = getLocale().toString(); 5873ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov HashMap<String, String> projectionMap = Maps.newHashMap(); 58745d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro String sectionHeading = String.format(AddressBookIndexQuery.SECTION_HEADING, sortKey); 5875bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov projectionMap.put(AddressBookIndexQuery.LETTER, 587624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro sectionHeading + " AS " + AddressBookIndexQuery.LETTER); 5877bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 58782ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki // If "what to count" is not specified, we just count all records. 58792ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki if (TextUtils.isEmpty(countExpression)) { 58802ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki countExpression = "*"; 58812ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki } 58822ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki 5883bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov /** 5884bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * Use the GET_PHONEBOOK_INDEX function, which is an android extension for SQLite3, 5885bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * to map the first letter of the sort key to a character that is traditionally 5886bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * used in phonebooks to represent that letter. For example, in Korean it will 5887bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * be the first consonant in the letter; for Japanese it will be Hiragana rather 5888bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * than Katakana. 5889bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov */ 5890ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.TITLE, 589124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro "GET_PHONEBOOK_INDEX(" + sectionHeading + ",'" + locale + "')" 5892bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov + " AS " + AddressBookIndexQuery.TITLE); 5893ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.COUNT, 58942ebc62b692be3aaaeafa01d658ae3cdfb25b728aMakoto Onuki "COUNT(" + countExpression + ") AS " + AddressBookIndexQuery.COUNT); 5895ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov qb.setProjectionMap(projectionMap); 5896ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5897f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov Cursor indexCursor = qb.query(db, AddressBookIndexQuery.COLUMNS, selection, selectionArgs, 5898ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY, null /* having */, 5899ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY + sortOrderSuffix); 5900ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5901ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov try { 5902f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov int groupCount = indexCursor.getCount(); 5903ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String titles[] = new String[groupCount]; 5904ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int counts[] = new int[groupCount]; 5905bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int indexCount = 0; 5906bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String currentTitle = null; 5907bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 5908bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // Since GET_PHONEBOOK_INDEX is a many-to-1 function, we may end up 5909bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // with multiple entries for the same title. The following code 5910bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // collapses those duplicates. 5911ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov for (int i = 0; i < groupCount; i++) { 5912f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.moveToNext(); 5913bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String title = indexCursor.getString(AddressBookIndexQuery.COLUMN_TITLE); 5914bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int count = indexCursor.getInt(AddressBookIndexQuery.COLUMN_COUNT); 5915bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount == 0 || !TextUtils.equals(title, currentTitle)) { 5916bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles[indexCount] = currentTitle = title; 5917bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount] = count; 5918bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov indexCount++; 5919bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } else { 5920bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount - 1] += count; 5921bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 5922bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 5923bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 5924bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount < groupCount) { 5925bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String[] newTitles = new String[indexCount]; 5926bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(titles, 0, newTitles, 0, indexCount); 5927bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles = newTitles; 5928bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 5929bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int[] newCounts = new int[indexCount]; 5930bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(counts, 0, newCounts, 0, indexCount); 5931bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts = newCounts; 5932ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5933ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 5934409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki final Bundle bundle = new Bundle(); 5935409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki bundle.putStringArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, titles); 5936409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki bundle.putIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS, counts); 5937409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki 5938409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki ((AbstractCursor) cursor).setExtras(bundle); 5939409605a187683155d9c6dbc2626b6419e3dd384eMakoto Onuki return cursor; 5940ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } finally { 5941f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.close(); 5942ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5943ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 5944ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 59452d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill /** 594692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Returns the contact Id for the contact identified by the lookupKey. 594792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Robust against changes in the lookup key: if the key has changed, will 594892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * look up the contact by the raw contact IDs or name encoded in the lookup 594992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * key. 59502d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill */ 59512d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill public long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 59525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 59535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 59545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 595592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov long contactId = -1; 59565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_PROFILE)) { 59575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // We should already be in a profile database context, so just look up a single contact. 59585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro contactId = lookupSingleContactId(db); 59595d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 59605d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 596192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_SOURCE_ID)) { 596292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdBySourceIds(db, segments); 596392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 596492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 596592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 596692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 596792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 596892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov boolean hasRawContactIds = 596992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID); 597092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds) { 597192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdByRawContactIds(db, segments); 597292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 597392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 597492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 597592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 597692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 597792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds 597892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME)) { 59795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 59805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 59815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 59825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 59835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 59845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 59855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro private long lookupSingleContactId(SQLiteDatabase db) { 59865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = db.query(Tables.CONTACTS, new String[] {Contacts._ID}, 59875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro null, null, null, null, null, "1"); 59885d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro try { 59895d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (c.moveToFirst()) { 59905d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return c.getLong(0); 59915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 59925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return -1; 59935d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 59945d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } finally { 59955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro c.close(); 59965d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 59975d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 59985d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 59995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 600043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String TABLE = Views.RAW_CONTACTS; 60015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 60035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 600443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 60055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 60065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 60075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 60085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 601043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int ACCOUNT_TYPE_AND_DATA_SET = 1; 60115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 60125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 60135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 60165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 60175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 60185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 60195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 60205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 602192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID) { 60225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 60235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 60245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 60275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 60285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 60305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 60315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 60325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 603343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String accountTypeAndDataSet = 603443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE_AND_DATA_SET); 60355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 60365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 603743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ContactLookupKey.getAccountHashCode(accountTypeAndDataSet, accountName); 60385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 60395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 60405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 604192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID 604292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 60435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 60445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 60455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 60465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 60505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 60515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 60545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 605692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByRawContactIdQuery { 605743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String TABLE = Views.RAW_CONTACTS; 60585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 60605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 606143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 60625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 606392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts._ID, 60645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 60655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 60665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 606743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int ACCOUNT_TYPE_AND_DATA_SET = 1; 60685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 606992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ID = 3; 60705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 607292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByRawContactIds(SQLiteDatabase db, 607392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 607492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 607592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(RawContacts._ID + " IN ("); 60765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 60775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 607892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 607992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(segment.rawContactId); 608092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(","); 60815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 60825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 608392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 608492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 60855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 608692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Cursor c = db.query(LookupByRawContactIdQuery.TABLE, LookupByRawContactIdQuery.COLUMNS, 608792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.toString(), null, null, null, null); 608892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov try { 608992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov while (c.moveToNext()) { 609043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String accountTypeAndDataSet = c.getString( 609143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro LookupByRawContactIdQuery.ACCOUNT_TYPE_AND_DATA_SET); 609292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountName = c.getString(LookupByRawContactIdQuery.ACCOUNT_NAME); 609392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int accountHashCode = 609443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ContactLookupKey.getAccountHashCode(accountTypeAndDataSet, accountName); 609592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String rawContactId = c.getString(LookupByRawContactIdQuery.ID); 609692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 609792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 609892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID 609992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 610092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && segment.rawContactId.equals(rawContactId)) { 610192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov segment.contactId = c.getLong(LookupByRawContactIdQuery.CONTACT_ID); 610292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov break; 610392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 610492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 610592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 610692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } finally { 610792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov c.close(); 61085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 611092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return getMostReferencedContactId(segments); 611192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 611292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 611392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByDisplayNameQuery { 611492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 611592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 611692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String COLUMNS[] = { 611792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.CONTACT_ID, 611843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro RawContacts.ACCOUNT_TYPE_AND_DATA_SET, 611992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 612092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 612192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov }; 612292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 612392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int CONTACT_ID = 0; 612443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro int ACCOUNT_TYPE_AND_DATA_SET = 1; 612592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_NAME = 2; 612692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int NORMALIZED_NAME = 3; 612792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 612892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 612992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 613092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 61315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 61325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 61335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 61345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 613592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 613692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 61375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 61385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 61395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 61425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 61435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 61445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 61465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 61475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 61485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 614943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String accountTypeAndDataSet = 615043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE_AND_DATA_SET); 61515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 61525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 615343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro ContactLookupKey.getAccountHashCode(accountTypeAndDataSet, accountName); 61545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 61555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 61565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 615792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if ((segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 615892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) 615992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 61605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 61615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 61625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 61635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 61675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 61685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 61715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 61725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 617392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private boolean lookupKeyContainsType(ArrayList<LookupKeySegment> segments, int lookupType) { 617492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 617592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 617692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == lookupType) { 617792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return true; 617892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 617992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 618092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 618192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return false; 618292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 618392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 6184ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateLookupKeyForRawContact(SQLiteDatabase db, long rawContactId) { 61855d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mAggregator.get().updateLookupKeyForRawContact(db, rawContactId); 6186ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov } 6187ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov 61885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 61895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 61905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 61915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 61925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 61935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 61955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 61965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 61975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 61985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 61995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 62005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 62015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 62025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 62035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 62045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 62055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 62065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 62075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 62085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 62095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 62105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 62125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 62135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 62175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 62185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 62195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 62205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 62225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 6223763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 6224763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 62254928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa setTablesAndProjectionMapForContacts(qb, uri, projection, false); 62262f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 62272f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 62282f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa /** 62294928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * @param includeDataUsageStat true when the table should include DataUsageStat table. 62304928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * Note that this uses INNER JOIN instead of LEFT OUTER JOIN, so some of data in Contacts 62314928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa * may be dropped. 62322f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa */ 62332f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 62344928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa String[] projection, boolean includeDataUsageStat) { 623582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 6236ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.CONTACTS); 62372f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 62382f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa // Just for frequently contacted contacts in Strequent Uri handling. 62394928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa if (includeDataUsageStat) { 62402f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa sb.append(" INNER JOIN " + 6241ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann Views.DATA_USAGE_STAT + " AS " + Tables.DATA_USAGE_STAT + 62422f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa " ON (" + 62432f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa DbQueryUtils.concatenateClauses( 62442f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa DataUsageStatColumns.CONCRETE_TIMES_USED + " > 0", 62454928b8c8c7a49ec088884cd9d330eeecc811dca9Daisuke Miyakawa RawContacts.CONTACT_ID + "=" + Views.CONTACTS + "." + Contacts._ID) + 62462f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa ")"); 62472f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa } 62482f830d3bb66f780937203e9738e046841a070e73Daisuke Miyakawa 62497ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts._ID); 62507ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 6251916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 6252916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 6253916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 6254916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 6255916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** 6256916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * Finds name lookup records matching the supplied filter, picks one arbitrary match per 6257916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * contact and joins that with other contacts tables. 6258916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov */ 6259916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void setTablesAndProjectionMapForContactsWithSnippet(SQLiteQueryBuilder qb, Uri uri, 62607ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov String[] projection, String filter, long directoryId) { 62617ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov 62627ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 6263ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.CONTACTS); 6264916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 626503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (filter != null) { 626603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov filter = filter.trim(); 626703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 626803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 626930cc766756461da8d53933f88ea01dd2272a90ebDmitri Plotnikov if (TextUtils.isEmpty(filter) || (directoryId != -1 && directoryId != Directory.DEFAULT)) { 627030cc766756461da8d53933f88ea01dd2272a90ebDmitri Plotnikov sb.append(" JOIN (SELECT NULL AS " + SearchSnippetColumns.SNIPPET + " WHERE 0)"); 62715e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } else { 62725e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov appendSearchIndexJoin(sb, uri, projection, filter); 62735e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 62747ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts._ID); 62757ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 627603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov qb.setTables(sb.toString()); 627703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionWithSnippetMap); 627803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 6279916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 628003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private void appendSearchIndexJoin( 628103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov StringBuilder sb, Uri uri, String[] projection, String filter) { 6282916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 62835d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, SearchSnippetColumns.SNIPPET)) { 628403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String[] args = null; 628503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov String snippetArgs = 628603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov getQueryParameter(uri, SearchSnippetColumns.SNIPPET_ARGS_PARAM_KEY); 628703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (snippetArgs != null) { 628803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov args = snippetArgs.split(","); 628903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 629003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 62915e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String startMatch = args != null && args.length > 0 ? args[0] 62925e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_START_MATCH; 62935e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String endMatch = args != null && args.length > 1 ? args[1] 62945e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_END_MATCH; 62955e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String ellipsis = args != null && args.length > 2 ? args[2] 62965e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_ELLIPSIS; 62975e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov int maxTokens = args != null && args.length > 3 ? Integer.parseInt(args[3]) 62985e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov : DEFAULT_SNIPPET_ARG_MAX_TOKENS; 62995e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 6300174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov appendSearchIndexJoin( 6301174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov sb, filter, true, startMatch, endMatch, ellipsis, maxTokens); 6302174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } else { 6303174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov appendSearchIndexJoin(sb, filter, false, null, null, null, 0); 6304174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 6305174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 6306174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 6307174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov public void appendSearchIndexJoin(StringBuilder sb, String filter, 6308174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean snippetNeeded, String startMatch, String endMatch, String ellipsis, 6309174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov int maxTokens) { 6310174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean isEmailAddress = false; 6311174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String emailAddress = null; 6312174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov boolean isPhoneNumber = false; 6313174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String phoneNumber = null; 6314174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String numberE164 = null; 6315174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 63163716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // If the query consists of a single word, we can do snippetizing after-the-fact for a 63173716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // performance boost. 63183716f1447ceb21180d1301790eabd8b9453f486dDave Santoro boolean singleTokenSearch = filter.split(QUERY_TOKENIZER_REGEX).length == 1; 63193716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 6320174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov if (filter.indexOf('@') != -1) { 63215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro emailAddress = mDbHelper.get().extractAddressFromEmailAddress(filter); 6322174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov isEmailAddress = !TextUtils.isEmpty(emailAddress); 6323174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } else { 6324174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov isPhoneNumber = isPhoneNumber(filter); 632504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (isPhoneNumber) { 632604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann phoneNumber = PhoneNumberUtils.normalizeNumber(filter); 632704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann numberE164 = PhoneNumberUtils.formatNumberToE164(phoneNumber, 63285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().getCountryIso()); 632904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 6330174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 6331174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 6332174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov sb.append(" JOIN (SELECT " + SearchIndexColumns.CONTACT_ID + " AS snippet_contact_id"); 6333174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov if (snippetNeeded) { 63345e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(", "); 63355e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov if (isEmailAddress) { 63363d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append("ifnull("); 63375e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 633804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("||(SELECT MIN(" + Email.ADDRESS + ")"); 633904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" FROM " + Tables.DATA_JOIN_RAW_CONTACTS); 634004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" WHERE " + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 634104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + RawContacts.CONTACT_ID + " AND " + Email.ADDRESS + " LIKE "); 634204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann DatabaseUtils.appendEscapedSQLString(sb, filter + "%"); 634304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(")||"); 63443d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 63453d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append(","); 63463716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 63473716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Optimization for single-token search. 63483716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (singleTokenSearch) { 63493716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 63503716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 63513716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 63523716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 63533d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append(")"); 63543d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov } else if (isPhoneNumber) { 63553d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov sb.append("ifnull("); 63563d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 635704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("||(SELECT MIN(" + Phone.NUMBER + ")"); 635804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" FROM " + 635904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann Tables.DATA_JOIN_RAW_CONTACTS + " JOIN " + Tables.PHONE_LOOKUP); 636004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" ON " + DataColumns.CONCRETE_ID); 636104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + Tables.PHONE_LOOKUP + "." + PhoneLookupColumns.DATA_ID); 636204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" WHERE " + Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 636304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("=" + RawContacts.CONTACT_ID); 636404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" AND " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 636504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(phoneNumber); 636604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("%'"); 636704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (!TextUtils.isEmpty(numberE164)) { 636804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(" OR " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '"); 636904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(numberE164); 637004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("%'"); 637104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 637204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append(")||"); 63735e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 63745e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 63753716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 63763716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Optimization for single-token search. 63773716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (singleTokenSearch) { 63783716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 63793716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 63803716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 63813716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 63825e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(")"); 638303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 638404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann final String normalizedFilter = NameNormalizer.normalize(filter); 638504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann if (!TextUtils.isEmpty(normalizedFilter)) { 63863716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // Optimization for single-token search. 63873716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (singleTokenSearch) { 63883716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(SearchIndexColumns.CONTENT); 63893716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 63903716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("(CASE WHEN EXISTS (SELECT 1 FROM "); 63913716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.RAW_CONTACTS + " AS rc INNER JOIN "); 63923716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.NAME_LOOKUP + " AS nl ON (rc." + RawContacts._ID); 63933716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("=nl." + NameLookupColumns.RAW_CONTACT_ID); 63943716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(") WHERE nl." + NameLookupColumns.NORMALIZED_NAME); 63953716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(" GLOB '" + normalizedFilter + "*' AND "); 63963716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("nl." + NameLookupColumns.NAME_TYPE + "="); 63973716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(NameLookupType.NAME_COLLATION_KEY + " AND "); 63983716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(Tables.SEARCH_INDEX + "." + SearchIndexColumns.CONTACT_ID); 63993716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append("=rc." + RawContacts.CONTACT_ID); 64003716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(") THEN NULL ELSE "); 64013716f1447ceb21180d1301790eabd8b9453f486dDave Santoro appendSnippetFunction(sb, startMatch, endMatch, ellipsis, maxTokens); 64023716f1447ceb21180d1301790eabd8b9453f486dDave Santoro sb.append(" END)"); 64033716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 640404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } else { 640504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann sb.append("NULL"); 640604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 640703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 64085e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" AS " + SearchSnippetColumns.SNIPPET); 64095e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 641003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 64115e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" FROM " + Tables.SEARCH_INDEX); 64125e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(" WHERE "); 64135e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(Tables.SEARCH_INDEX + " MATCH "); 64145e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov if (isEmailAddress) { 64152352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, "\"" + sanitizeMatch(filter) + "*\""); 64163d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov } else if (isPhoneNumber) { 64172352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, 641804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann "\"" + sanitizeMatch(filter) + "*\" OR \"" + phoneNumber + "*\"" 64192352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov + (numberE164 != null ? " OR \"" + numberE164 + "\"" : "")); 642003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } else { 64212352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, sanitizeMatch(filter) + "*"); 64229c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov } 642303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov sb.append(") ON (" + Contacts._ID + "=snippet_contact_id)"); 6424a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov } 6425a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov 64262352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov private String sanitizeMatch(String filter) { 64272352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov // TODO more robust preprocessing of match expressions 64282352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov return filter.replace('-', ' ').replace('\"', ' '); 64292352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov } 64302352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov 64315e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov private void appendSnippetFunction( 64325e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov StringBuilder sb, String startMatch, String endMatch, String ellipsis, int maxTokens) { 64335e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append("snippet(" + Tables.SEARCH_INDEX + ","); 64345e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, startMatch); 64355e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 64365e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, endMatch); 64375e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(","); 64385e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, ellipsis); 64395e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 64405e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov // The index of the column used for the snippet, "content" 64415e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(",1,"); 64425e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(maxTokens); 64435e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov sb.append(")"); 64445e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 64455e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 6446763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 6447763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 6448ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.RAW_CONTACTS); 6449763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 6450763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 645143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro appendAccountFromParameter(qb, uri, true); 6452763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 6453763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 6454a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForRawEntities(SQLiteQueryBuilder qb, Uri uri) { 6455ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann qb.setTables(Views.RAW_ENTITIES); 6456a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sRawEntityProjectionMap); 645743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro appendAccountFromParameter(qb, uri, true); 645846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 645946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 646082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 646182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 646246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, distinct, null); 646346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 646446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 646546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 646646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * @param usageType when non-null {@link Tables#DATA_USAGE_STAT} is joined with the specified 646746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * type. 646846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 646946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 647046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa String[] projection, boolean distinct, Integer usageType) { 647182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 6472ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.DATA); 647382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 647482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 6475a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, RawContacts.CONTACT_ID); 6476a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 6477a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 6478a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 64793296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 648046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (usageType != null) { 648146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa appendDataUsageStatJoin(sb, usageType, DataColumns.CONCRETE_ID); 648246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 648346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 648482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 6485f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov 6486f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov boolean useDistinct = distinct 64875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro || !mDbHelper.get().isInProjection(projection, DISTINCT_DATA_PROHIBITING_COLUMNS); 6488f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov qb.setDistinct(useDistinct); 6489f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov qb.setProjectionMap(useDistinct ? sDistinctDataProjectionMap : sDataProjectionMap); 649043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro appendAccountFromParameter(qb, uri, true); 6491ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 6492ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 64930a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 64940a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 64950a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 6496ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.DATA); 64970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 6498a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 6499a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 65000a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 6501a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 6502a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 6503a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6504a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 65053b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void setTablesAndProjectionMapForStreamItems(SQLiteQueryBuilder qb) { 65069b002837367674b7403769f52dc50ab4dbecef71Daniel Lehmann qb.setTables(Views.STREAM_ITEMS); 65073b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.setProjectionMap(sStreamItemsProjectionMap); 65083b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 65093b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 65103b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann private void setTablesAndProjectionMapForStreamItemPhotos(SQLiteQueryBuilder qb) { 65111dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro qb.setTables(Tables.PHOTO_FILES 65121dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + " JOIN " + Tables.STREAM_ITEM_PHOTOS + " ON (" 65131dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + StreamItemPhotosColumns.CONCRETE_PHOTO_FILE_ID + "=" 65141dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + PhotoFilesColumns.CONCRETE_ID 65151dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + ") JOIN " + Tables.STREAM_ITEMS + " ON (" 65161dfa964f2e1756e27b36f99421bd403c84ea0a5fDave Santoro + StreamItemPhotosColumns.CONCRETE_STREAM_ITEM_ID + "=" 65170bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + StreamItemsColumns.CONCRETE_ID + ")" 65180bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + " JOIN " + Tables.RAW_CONTACTS + " ON (" 65190bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + StreamItemsColumns.CONCRETE_RAW_CONTACT_ID + "=" + RawContactsColumns.CONCRETE_ID 65200bf6b318e3c994294d4a885f57906debd4a0e64eDaniel Lehmann + ")"); 65213b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann qb.setProjectionMap(sStreamItemPhotosProjectionMap); 65223b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann } 65233b505de6c622d20d40b85b361c1437a89aef82deDaniel Lehmann 6524a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void setTablesAndProjectionMapForEntities(SQLiteQueryBuilder qb, Uri uri, 6525a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String[] projection) { 6526a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 6527ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann sb.append(Views.ENTITIES); 6528a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" data"); 6529a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6530a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactPresenceJoin(sb, projection, Contacts.Entity.CONTACT_ID); 6531a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 6532a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataPresenceJoin(sb, projection, Contacts.Entity.DATA_ID); 6533a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov appendDataStatusUpdateJoin(sb, projection, Contacts.Entity.DATA_ID); 6534a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6535a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setTables(sb.toString()); 6536a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sEntityProjectionMap); 653743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro appendAccountFromParameter(qb, uri, true); 6538a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6539a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6540a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactStatusUpdateJoin(StringBuilder sb, String[] projection, 6541a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String lastStatusUpdateIdColumn) { 65425d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, 6543a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS, 6544a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 6545a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 6546a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 6547a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 6548a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 6549a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.ALIAS + 6550a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + lastStatusUpdateIdColumn + "=" 6551a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 65520a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 6553a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 65540a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 6555a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataStatusUpdateJoin(StringBuilder sb, String[] projection, 6556a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 65575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, 65580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 65590a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 65600a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 65610a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 65620a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 65630a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 6564a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 6565a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + dataIdColumn + ")"); 65660a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 6567a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6568a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 656946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private void appendDataUsageStatJoin(StringBuilder sb, int usageType, String dataIdColumn) { 657046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" LEFT OUTER JOIN " + Tables.DATA_USAGE_STAT + 657146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa " ON (" + DataUsageStatColumns.CONCRETE_DATA_ID + "=" + dataIdColumn + 657246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa " AND " + DataUsageStatColumns.CONCRETE_USAGE_TYPE + "=" + usageType + ")"); 657346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 657446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 6575a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendContactPresenceJoin(StringBuilder sb, String[] projection, 6576a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactIdColumn) { 65775d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, 6578a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Contacts.CONTACT_PRESENCE, Contacts.CONTACT_CHAT_CAPABILITY)) { 6579a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 6580a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + contactIdColumn + " = " 6581a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + ")"); 6582a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6583a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6584a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 6585a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private void appendDataPresenceJoin(StringBuilder sb, String[] projection, 6586a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String dataIdColumn) { 65875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mDbHelper.get().isInProjection(projection, Data.PRESENCE, Data.CHAT_CAPABILITY)) { 6588a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 6589a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov " ON (" + StatusUpdates.DATA_ID + "=" + dataIdColumn + ")"); 6590a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6591a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 6592a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 659324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro private boolean appendLocalDirectorySelectionIfNeeded(SQLiteQueryBuilder qb, long directoryId) { 6594385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov if (directoryId == Directory.DEFAULT) { 6595385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov qb.appendWhere(Contacts._ID + " IN " + Tables.DEFAULT_DIRECTORY); 659624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return true; 6597385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov } else if (directoryId == Directory.LOCAL_INVISIBLE){ 6598385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov qb.appendWhere(Contacts._ID + " NOT IN " + Tables.DEFAULT_DIRECTORY); 659924c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return true; 660024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 660124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro return false; 660224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro } 660324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro 660443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri, 660543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro boolean includeDataSet) { 6606f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 6607f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 660843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro final String dataSet = getQueryParameter(uri, RawContacts.DATA_SET); 6609e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6610e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 6611e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 6612e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 66135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 6614fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 6615e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 6616e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6617e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 6618e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 6619e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 6620e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 662143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro String toAppend = RawContacts.ACCOUNT_NAME + "=" 66224a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 66234a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 662443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro + DatabaseUtils.sqlEscapeString(accountType); 662543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (includeDataSet) { 662643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (dataSet == null) { 662743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro toAppend += " AND " + RawContacts.DATA_SET + " IS NULL"; 662843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } else { 662943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro toAppend += " AND " + RawContacts.DATA_SET + "=" + 663043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro DatabaseUtils.sqlEscapeString(dataSet); 663143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 663243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 663343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro qb.appendWhere(toAppend); 66344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 66354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 66364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 66374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 66384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 6639e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 6640f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 6641f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 664243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro final String dataSet = getQueryParameter(uri, RawContacts.DATA_SET); 6643e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6644e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 6645e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 6646e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 66475d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 6648fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 6649e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 6650e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 6651e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 6652e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 6653e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 6654e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 6655e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 6656e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 6657e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 6658e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 665943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (!TextUtils.isEmpty(dataSet)) { 666043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro selectionSb.append(" AND " + RawContacts.DATA_SET + "=") 666143368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro .append(DatabaseUtils.sqlEscapeString(dataSet)); 666243368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro } 6663e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 6664e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 6665e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 6666e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 6667e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 6668e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 6669e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 6670e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 6671e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 6672e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 6673e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 66747e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 6675c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 6676c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 6677c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 6678c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 6679c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 6680f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String getLimit(Uri uri) { 66812e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov String limitParam = getQueryParameter(uri, ContactsContract.LIMIT_PARAM_KEY); 6682c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 6683c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 6684c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6685c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 6686c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 6687c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 6688c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 6689c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 6690c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 6691c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6692c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 6693c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 6694c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 6695c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 6696c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6697c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 6698c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 6699b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 6700f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 6701f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (mode.equals("r")) { 6702f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro waitForAccess(mReadAccessLatch); 6703f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 6704f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro waitForAccess(mWriteAccessLatch); 6705f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 67065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mapsToProfileDb(uri)) { 67075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToProfileMode(); 67085d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileProvider.openAssetFile(uri, mode); 67095d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 67105d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 67115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mode.equals("r")) { 67125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDb = mDbHelper.get().getReadableDatabase(); 67135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 67145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDb = mDbHelper.get().getWritableDatabase(); 67155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 67165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return openAssetFileLocal(uri, mode); 67175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 67185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 67195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 67205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro public AssetFileDescriptor openAssetFileLocal(Uri uri, String mode) 67215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throws FileNotFoundException { 67225d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro 67235d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // Default active DB to the contacts DB if none has been set. 67245d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (mActiveDb.get() == null) { 67255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(mDb); 67265d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 6727415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 6728b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 6729b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 6730a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case CONTACTS_ID_PHOTO: { 673124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 67325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return openPhotoAssetFile(mActiveDb.get(), uri, mode, 673324c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro Data._ID + "=" + Contacts.PHOTO_ID + " AND " + 673424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro RawContacts.CONTACT_ID + "=?", 673524c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro new String[]{String.valueOf(rawContactId)}); 6736e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 6737b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 6738f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_ID_DISPLAY_PHOTO: { 6739f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (!mode.equals("r")) { 6740f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new IllegalArgumentException( 6741f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Display photos retrieved by contact ID can only be read."); 6742f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6743f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long contactId = Long.parseLong(uri.getPathSegments().get(1)); 67445d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = mActiveDb.get().query(Tables.CONTACTS, 6745f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro new String[]{Contacts.PHOTO_FILE_ID}, 6746f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Contacts._ID + "=?", new String[]{String.valueOf(contactId)}, 6747f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro null, null, null); 6748f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6749f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 6750f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = c.getLong(0); 6751f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 6752f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 6753f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 6754f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6755f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6756f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6757f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_DISPLAY_PHOTO: 6758f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_ID_DISPLAY_PHOTO: { 6759f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (!mode.equals("r")) { 6760f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new IllegalArgumentException( 6761f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Display photos retrieved by contact lookup key can only be read."); 6762f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6763f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro List<String> pathSegments = uri.getPathSegments(); 6764f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro int segmentCount = pathSegments.size(); 6765f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (segmentCount < 4) { 67665d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new IllegalArgumentException(mDbHelper.get().exceptionMessage( 6767f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Missing a lookup key", uri)); 6768f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6769f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String lookupKey = pathSegments.get(2); 6770f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String[] projection = new String[]{Contacts.PHOTO_FILE_ID}; 6771f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (segmentCount == 5) { 6772f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long contactId = Long.parseLong(pathSegments.get(3)); 6773f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 6774f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 67755d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri, 6776f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro projection, null, null, null, null, null, 6777f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey); 6778f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (c != null) { 6779f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6780f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 6781f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = c.getLong(c.getColumnIndex(Contacts.PHOTO_FILE_ID)); 6782f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 6783f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 6784f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 6785f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6786f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6787f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6788f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6789f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 6790f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro setTablesAndProjectionMapForContacts(qb, uri, projection); 67915d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 67925d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), projection, Contacts._ID + "=?", 6793f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro new String[]{String.valueOf(contactId)}, null, null, null); 6794f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6795f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 6796f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = c.getLong(c.getColumnIndex(Contacts.PHOTO_FILE_ID)); 6797f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 6798f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 6799f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 6800f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6801f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6802f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6803f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case RAW_CONTACTS_ID_DISPLAY_PHOTO: { 6804f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 6805f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro boolean writeable = !mode.equals("r"); 6806f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6807f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Find the primary photo data record for this raw contact. 6808f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 6809f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String[] projection = new String[]{Data._ID, Photo.PHOTO_FILE_ID}; 6810f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro setTablesAndProjectionMapForData(qb, uri, projection, false); 68115d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor c = qb.query(mActiveDb.get(), projection, 6812f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Data.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE + "=?", 6813f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro new String[]{String.valueOf(rawContactId), Photo.CONTENT_ITEM_TYPE}, 6814f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro null, null, Data.IS_PRIMARY + " DESC"); 6815f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long dataId = 0; 6816f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = 0; 6817f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6818f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (c.getCount() >= 1) { 6819f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.moveToFirst(); 6820f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro dataId = c.getLong(0); 6821f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro photoFileId = c.getLong(1); 6822f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6823f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } finally { 6824f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro c.close(); 6825f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6826f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6827f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // If writeable, open a writeable file descriptor that we can monitor. 6828f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // When the caller finishes writing content, we'll process the photo and 6829f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // update the data record. 6830f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (writeable) { 6831f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForWrite(rawContactId, dataId, uri, mode); 6832f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 6833f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 6834f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6835f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6836f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6837f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case DISPLAY_PHOTO: { 6838f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro long photoFileId = ContentUris.parseId(uri); 6839f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (!mode.equals("r")) { 6840f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new IllegalArgumentException( 6841f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro "Display photos retrieved by key can only be read."); 6842f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6843f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return openDisplayPhotoForRead(photoFileId); 6844f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6845f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6846e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov case DATA_ID: { 684724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro long dataId = Long.parseLong(uri.getPathSegments().get(1)); 68485d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return openPhotoAssetFile(mActiveDb.get(), uri, mode, 6849e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov Data._ID + "=? AND " + Data.MIMETYPE + "='" + Photo.CONTENT_ITEM_TYPE + "'", 685024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro new String[]{String.valueOf(dataId)}); 6851d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 6852d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 6853fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen case PROFILE_AS_VCARD: { 6854fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // When opening a contact as file, we pass back contents as a 6855fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // vCard-encoded stream. We build into a local buffer first, 6856fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen // then pipe into MemoryFile once the exact size is known. 6857fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 6858fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(uri, localStream, null, null); 6859fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen return buildAssetFileDescriptor(localStream); 6860fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen } 686142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 6862fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen case CONTACTS_AS_VCARD: { 686342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // When opening a contact as file, we pass back contents as a 686442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // vCard-encoded stream. We build into a local buffer first, 686542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // then pipe into MemoryFile once the exact size is known. 686642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 6867fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(uri, localStream, null, null); 6868f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return buildAssetFileDescriptor(localStream); 686942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 687042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 687142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 687242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKeys = uri.getPathSegments().get(2); 687342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String[] loopupKeyList = lookupKeys.split(":"); 687442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final StringBuilder inBuilder = new StringBuilder(); 6875fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen Uri queryUri = Contacts.CONTENT_URI; 687642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann int index = 0; 6877fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen 6878d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // SQLite has limits on how many parameters can be used 6879d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // so the IDs are concatenated to a query string here instead 688042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann for (String lookupKey : loopupKeyList) { 688142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann if (index == 0) { 6882d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append("("); 688342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } else { 6884d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append(","); 688542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 68865d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro // TODO: Figure out what to do if the profile contact is in the list. 68875d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey); 688824c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro inBuilder.append(contactId); 688942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann index++; 689042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 689142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann inBuilder.append(')'); 689242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + " IN " + inBuilder.toString(); 6893d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 6894d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 6895d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 6896d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 6897d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 6898fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen outputRawContactsAsVCard(queryUri, localStream, selection, null); 6899f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return buildAssetFileDescriptor(localStream); 6900d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 6901b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 6902b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 69035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new FileNotFoundException(mDbHelper.get().exceptionMessage( 69045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro "File does not exist", uri)); 6905b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 6906b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 6907b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 6908afc8e7ad6e5208db6c87b8500ecc1246ad966d62Dave Santoro private AssetFileDescriptor openPhotoAssetFile(SQLiteDatabase db, Uri uri, String mode, 6909afc8e7ad6e5208db6c87b8500ecc1246ad966d62Dave Santoro String selection, String[] selectionArgs) 6910e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throws FileNotFoundException { 6911e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov if (!"r".equals(mode)) { 69125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro throw new FileNotFoundException(mDbHelper.get().exceptionMessage("Mode " + mode 6913e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov + " not supported.", uri)); 6914e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 6915e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 6916e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String sql = 6917ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann "SELECT " + Photo.PHOTO + " FROM " + Views.DATA + 6918e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov " WHERE " + selection; 691908ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood try { 6920f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor( 6921f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert DatabaseUtils.blobFileDescriptorForQuery(db, sql, selectionArgs)); 692208ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } catch (SQLiteDoneException e) { 692308ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood // this will happen if the DB query returns no rows (i.e. contact does not exist) 692408ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood throw new FileNotFoundException(uri.toString()); 692508ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } 6926e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 6927e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 6928f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 6929f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Opens a display photo from the photo store for reading. 6930f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param photoFileId The display photo file ID 6931f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @return An asset file descriptor that allows the file to be read. 6932f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @throws FileNotFoundException If no photo file for the given ID exists. 6933f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 6934f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private AssetFileDescriptor openDisplayPhotoForRead(long photoFileId) 6935f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throws FileNotFoundException { 69365d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PhotoStore.Entry entry = mPhotoStore.get().get(photoFileId); 6937f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (entry != null) { 6938f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return makeAssetFileDescriptor( 6939f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ParcelFileDescriptor.open(new File(entry.path), 6940f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ParcelFileDescriptor.MODE_READ_ONLY), 6941f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro entry.size); 6942f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 6943f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS); 6944f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro throw new FileNotFoundException("No photo file found for ID " + photoFileId); 6945f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6946f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6947f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6948f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 6949f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * Opens a file descriptor for a photo to be written. When the caller completes writing 6950f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * to the file (closing the output stream), the image will be parsed out and processed. 6951f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * If processing succeeds, the given raw contact ID's primary photo record will be 6952f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * populated with the inserted image (if no primary photo record exists, the data ID can 6953f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * be left as 0, and a new data record will be inserted). 6954f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param rawContactId Raw contact ID this photo entry should be associated with. 6955f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param dataId Data ID for a photo mimetype that will be updated with the inserted 6956f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * image. May be set to 0, in which case the inserted image will trigger creation 6957f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * of a new primary photo image data row for the raw contact. 6958f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param uri The URI being used to access this file. 6959f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @param mode Read/write mode string. 6960f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * @return An asset file descriptor the caller can use to write an image file for the 6961f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro * raw contact. 6962f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 6963f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private AssetFileDescriptor openDisplayPhotoForWrite(long rawContactId, long dataId, Uri uri, 6964f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro String mode) { 6965f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6966c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro ParcelFileDescriptor[] pipeFds = ParcelFileDescriptor.createPipe(); 6967c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro PipeMonitor pipeMonitor = new PipeMonitor(rawContactId, dataId, pipeFds[0]); 6968c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro pipeMonitor.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[]) null); 6969c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro return new AssetFileDescriptor(pipeFds[1], 0, AssetFileDescriptor.UNKNOWN_LENGTH); 6970f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } catch (IOException ioe) { 6971f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro Log.e(TAG, "Could not create temp image file in mode " + mode); 6972f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return null; 6973f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6974f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6975f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6976f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro /** 6977c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro * Async task that monitors the given file descriptor (the read end of a pipe) for 6978c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro * the writer finishing. If the data from the pipe contains a valid image, the image 6979c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro * is either inserted into the given raw contact or updated in the given data row. 6980f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro */ 6981c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro private class PipeMonitor extends AsyncTask<Object, Object, Object> { 6982c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro private final ParcelFileDescriptor mDescriptor; 6983f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private final long mRawContactId; 6984f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro private final long mDataId; 6985c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro private PipeMonitor(long rawContactId, long dataId, ParcelFileDescriptor descriptor) { 6986f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mRawContactId = rawContactId; 6987f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mDataId = dataId; 6988c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro mDescriptor = descriptor; 6989f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 6990f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 6991f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro @Override 6992c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro protected Object doInBackground(Object... params) { 6993c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro AutoCloseInputStream is = new AutoCloseInputStream(mDescriptor); 6994f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro try { 6995c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro Bitmap b = BitmapFactory.decodeStream(is); 6996f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (b != null) { 6997fa4db3db4146a26f154ef2e89352ad70a5415b8eDaniel Lehmann waitForAccess(mWriteAccessLatch); 6998f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro PhotoProcessor processor = new PhotoProcessor(b, mMaxDisplayPhotoDim, 6999f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro mMaxThumbnailPhotoDim); 7000f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7001f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Store the compressed photo in the photo store. 70025d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PhotoStore photoStore = ContactsContract.isProfileId(mRawContactId) 70035d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro ? mProfilePhotoStore 70045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro : mContactsPhotoStore; 70055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long photoFileId = photoStore.insert(processor); 7006f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7007c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro // Depending on whether we already had a data row to attach the photo 7008c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro // to, do an update or insert. 7009f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (mDataId != 0) { 7010f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Update the data record with the new photo. 7011f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ContentValues updateValues = new ContentValues(); 7012f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7013f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Signal that photo processing has already been handled. 7014f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.put(DataRowHandlerForPhoto.SKIP_PROCESSING_KEY, true); 7015f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7016f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (photoFileId != 0) { 7017f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.put(Photo.PHOTO_FILE_ID, photoFileId); 7018f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7019f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro updateValues.put(Photo.PHOTO, processor.getThumbnailPhotoBytes()); 7020c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro update(ContentUris.withAppendedId(Data.CONTENT_URI, mDataId), 7021c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro updateValues, null, null); 7022f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } else { 7023f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Insert a new primary data record with the photo. 7024f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro ContentValues insertValues = new ContentValues(); 7025f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7026f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro // Signal that photo processing has already been handled. 7027f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(DataRowHandlerForPhoto.SKIP_PROCESSING_KEY, true); 7028f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7029f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 7030f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Data.IS_PRIMARY, 1); 7031f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro if (photoFileId != 0) { 7032f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Photo.PHOTO_FILE_ID, photoFileId); 7033f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7034f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues.put(Photo.PHOTO, processor.getThumbnailPhotoBytes()); 7035f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insert(RawContacts.CONTENT_URI.buildUpon() 7036f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .appendPath(String.valueOf(mRawContactId)) 7037f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro .appendPath(RawContacts.Data.CONTENT_DIRECTORY).build(), 7038f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro insertValues); 7039f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7040c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro 7041f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7042c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro } catch (IOException e) { 7043c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro throw new RuntimeException(e); 7044f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7045c6eab5080340824edd2c6676c4e6b96e142f87e4Dave Santoro return null; 7046f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7047f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro } 7048f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro 7049d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 7050d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7051d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 7052f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert * Returns an {@link AssetFileDescriptor} backed by the 7053d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 7054d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 7055f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 7056d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 7057d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 7058d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7059d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 7060d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7061f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor( 7062f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert ParcelFileDescriptor.fromData(byteData, CONTACT_MEMORY_FILE_NAME), 7063f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert byteData.length); 7064d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 7065ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert Log.w(TAG, "Problem writing stream into an ParcelFileDescriptor: " + e.toString()); 7066ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert return null; 7067d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7068d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7069d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7070f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor makeAssetFileDescriptor(ParcelFileDescriptor fd) { 7071f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return makeAssetFileDescriptor(fd, AssetFileDescriptor.UNKNOWN_LENGTH); 7072f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 7073f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 7074f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert private AssetFileDescriptor makeAssetFileDescriptor(ParcelFileDescriptor fd, long length) { 7075f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert return fd != null ? new AssetFileDescriptor(fd, 0, length) : null; 7076f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 7077f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 7078d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 7079d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 7080d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 7081d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 7082d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 7083fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen private void outputRawContactsAsVCard(Uri uri, OutputStream stream, 7084fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen String selection, String[] selectionArgs) { 7085d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 7086dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen int vcardconfig = VCardConfig.VCARD_TYPE_DEFAULT; 7087fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen if(uri.getBooleanQueryParameter( 7088fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen Contacts.QUERY_PARAMETER_VCARD_NO_PHOTO, false)) { 7089dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen vcardconfig |= VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT; 7090dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen } 70917a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa final VCardComposer composer = 7092dfa6d58328345c7c91f2467d29189a57b96bfe2aMartijn Coenen new VCardComposer(context, vcardconfig, false); 7093108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Writer writer = null; 7094108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa try { 7095108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer = new BufferedWriter(new OutputStreamWriter(stream)); 7096fdd04bc3a972cd72dfe7bf925e1624d656b34cf7Martijn Coenen if (!composer.init(uri, selection, selectionArgs, null)) { 7097108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.w(TAG, "Failed to init VCardComposer"); 7098108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return; 7099108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 7100d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 7101108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa while (!composer.isAfterLast()) { 7102108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer.write(composer.createOneEntry()); 7103108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 7104108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } catch (IOException e) { 7105108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.e(TAG, "IOException: " + e); 7106108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } finally { 7107108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa composer.terminate(); 7108108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa if (writer != null) { 7109108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa try { 7110108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa writer.close(); 7111108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } catch (IOException e) { 7112108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa Log.w(TAG, "IOException during closing output stream: " + e); 7113108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa } 7114d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7115d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7116d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 7117b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 71184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 71194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 7120415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 7121415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov waitForAccess(mReadAccessLatch); 7122415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 7123a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 71244f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 7125b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 7126be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 71272d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill case CONTACTS_LOOKUP: 7128b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 7129b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 713024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: 7131b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 7132f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 713342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: 713424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: 7135f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 7136f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov case CONTACTS_ID_PHOTO: 7137f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_ID_DISPLAY_PHOTO: 7138f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_DISPLAY_PHOTO: 7139f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case CONTACTS_LOOKUP_ID_DISPLAY_PHOTO: 7140f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case RAW_CONTACTS_ID_DISPLAY_PHOTO: 7141f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro case DISPLAY_PHOTO: 7142f547fd54d7933e1c03af4a8dc10560c71c38f6b8Dave Santoro return "image/jpeg"; 7143b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 714424c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS: 7145be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 7146b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 714724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID: 7148b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 7149f481f22a9323fe338672f99b88b26c5f0725cd42David Brown case DATA: 715024c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_DATA: 7151f481f22a9323fe338672f99b88b26c5f0725cd42David Brown return Data.CONTENT_TYPE; 7152508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 71535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro long id = ContentUris.parseId(uri); 71545d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (ContactsContract.isProfileId(id)) { 71555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mProfileHelper.getDataMimeType(id); 71565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } else { 71575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro return mContactsHelper.getDataMimeType(id); 71585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 715948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 716048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 716148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 716248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 71639005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov case PHONE_LOOKUP: 71649005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov return PhoneLookup.CONTENT_TYPE; 716548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 716648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 716748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 716848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 716948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 717048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 717148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 717248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 7173b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 7174b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 7175b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 7176b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 7177b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 7178b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 7179b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 7180b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 7181c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 7182c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 7183c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 7184c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 7185d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES: 7186d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_TYPE; 7187d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case DIRECTORIES_ID: 7188d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return Directory.CONTENT_ITEM_TYPE; 7189af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS: 7190af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.CONTENT_TYPE; 7191af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_ID: 7192af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.CONTENT_ITEM_TYPE; 7193af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_ID_PHOTOS: 7194af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.StreamItemPhotos.CONTENT_TYPE; 7195af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_ID_PHOTOS_ID: 7196af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki return StreamItems.StreamItemPhotos.CONTENT_ITEM_TYPE; 7197af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki case STREAM_ITEMS_PHOTOS: 7198af43bfb95070c234ae7090f6041f6fc62366313aMakoto Onuki throw new UnsupportedOperationException("Not supported for write-only URI " + uri); 719961efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 720061efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 72014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 72024f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 72037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 720409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov public String[] getDefaultProjection(Uri uri) { 720509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov final int match = sUriMatcher.match(uri); 720609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov switch (match) { 720709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS: 720809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP: 720909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_ID: 721009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_LOOKUP_ID: 721109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 721224c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE: 721309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsProjectionMap.getColumnNames(); 721409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 72158727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov case CONTACTS_ID_ENTITIES: 721624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_ENTITIES: 72178727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov return sEntityProjectionMap.getColumnNames(); 72188727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov 721909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_VCARD: 722009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case CONTACTS_AS_MULTI_VCARD: 722124c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_AS_VCARD: 722209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sContactsVCardProjectionMap.getColumnNames(); 722309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 722409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS: 722509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case RAW_CONTACTS_ID: 722624c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS: 722724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_RAW_CONTACTS_ID: 722809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sRawContactsProjectionMap.getColumnNames(); 722909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 723009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DATA_ID: 723109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES: 723209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONES_ID: 723309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS: 723409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case EMAILS_ID: 723509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS: 723609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case POSTALS_ID: 723724c1d384b45a6d3c1cc959062a9d4308335fabbfDave Santoro case PROFILE_DATA: 723809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDataProjectionMap.getColumnNames(); 723909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 724009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case PHONE_LOOKUP: 724109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sPhoneLookupProjectionMap.getColumnNames(); 724209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 724309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 724409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 724509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sAggregationExceptionsProjectionMap.getColumnNames(); 724609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 724709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case SETTINGS: 724809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sSettingsProjectionMap.getColumnNames(); 724909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 725009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES: 725109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov case DIRECTORIES_ID: 725209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return sDirectoryProjectionMap.getColumnNames(); 725309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 725409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov default: 725509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return null; 725609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 725709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 725809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 7259f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 7260f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 7261f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 7262f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 7263f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7264f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 7265f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 7266f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 7267f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 72685d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mDbHelper.get().insertNameLookup(rawContactId, dataId, lookupType, name); 7269f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7270f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 7271f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 7272f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 7273d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov return mCommonNicknameCache.getCommonNicknameClusters(normalizedName); 7274f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7275f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 7276f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 72772d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 7278d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 7279d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 7280d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 7281d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 7282d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 7283d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 7284d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 7285e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 7286916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 7287916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + "))"); 7288e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 7289e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 72909a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov public boolean isPhoneNumber(String filter) { 72919a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov boolean atLeastOneDigit = false; 72929a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov int len = filter.length(); 72939a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov for (int i = 0; i < len; i++) { 72949a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov char c = filter.charAt(i); 72959a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (c >= '0' && c <= '9') { 72969a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov atLeastOneDigit = true; 72979a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } else if (c != '*' && c != '#' && c != '+' && c != 'N' && c != '.' && c != ';' 72989a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov && c != '-' && c != '(' && c != ')' && c != ' ') { 72999a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return false; 73009a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 73019a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 73029a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return atLeastOneDigit; 73039a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 73049a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 73054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 73067a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * Takes components of a name from the query parameters and returns a cursor with those 73077a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * components as well as all missing components. There is no database activity involved 73087a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov * in this so the call can be made on the UI thread. 73097a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov */ 73107a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private Cursor completeName(Uri uri, String[] projection) { 73117a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (projection == null) { 73127a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov projection = sDataProjectionMap.getColumnNames(); 73137a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 73147a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 73157a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ContentValues values = new ContentValues(); 7316f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov DataRowHandlerForStructuredName handler = (DataRowHandlerForStructuredName) 7317f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov getDataRowHandler(StructuredName.CONTENT_ITEM_TYPE); 73187a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 73197a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov copyQueryParamsToContentValues(values, uri, 73207a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.DISPLAY_NAME, 73217a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PREFIX, 73227a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.GIVEN_NAME, 73237a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.MIDDLE_NAME, 73247a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.FAMILY_NAME, 73257a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.SUFFIX, 73267a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_NAME, 73277a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_FAMILY_NAME, 73287a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_MIDDLE_NAME, 73297a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov StructuredName.PHONETIC_GIVEN_NAME 73307a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ); 73317a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 73327a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov handler.fixStructuredNameComponents(values, values); 73337a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 73347a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 73357a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov Object[] row = new Object[projection.length]; 73367a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (int i = 0; i < projection.length; i++) { 73377a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov row[i] = values.get(projection[i]); 73387a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 73397a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov cursor.addRow(row); 73407a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return cursor; 73417a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 73427a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 73437a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private void copyQueryParamsToContentValues(ContentValues values, Uri uri, String... columns) { 73447a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (String column : columns) { 73457a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov String param = uri.getQueryParameter(column); 73467a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (param != null) { 73477a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov values.put(column, param); 73487a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 73497a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 73507a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 73517a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 73527a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 73537a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov /** 73544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 73554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 73564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 7357b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 7358b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 7359b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 7360b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 7361b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 73624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 73634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 7364b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 7365b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 7366b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 7367caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 73685e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 73695e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 73705e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 73715e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 73725e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 73735e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 73745e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 73755e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 73765e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 73775e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 73785e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 7379caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 7380caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 7381caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 73825f1f4a062ac34d75d2dbf586702cbeb121cf09caDmitri Plotnikov Account[] accounts = accountManager.getAccountsByType(DEFAULT_ACCOUNT_TYPE); 7383caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 7384caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 7385caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 7386caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 73876f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 7388caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 73896f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 7390caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 7391f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 739273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov /** 739343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro * Returns true if the specified account type and data set is writable. 739473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov */ 739543368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro protected boolean isWritableAccountWithDataSet(String accountTypeAndDataSet) { 739643368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro if (accountTypeAndDataSet == null) { 7397bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov return true; 7398bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov } 7399bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov 740043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro Boolean writable = mAccountWritability.get(accountTypeAndDataSet); 740173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable != null) { 740273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 740373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 740473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 7405627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov IContentService contentService = ContentResolver.getContentService(); 7406627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 740743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro // TODO(dsantoro): Need to update this logic to allow for sub-accounts. 7408627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 7409627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (ContactsContract.AUTHORITY.equals(sync.authority) && 741043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro accountTypeAndDataSet.equals(sync.accountType)) { 741173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = sync.supportsUploading(); 741273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov break; 7413627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 7414627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 7415627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } catch (RemoteException e) { 7416627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 7417627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 741873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 741973f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable == null) { 742073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = false; 742173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 742273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 742343368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro mAccountWritability.put(accountTypeAndDataSet, writable); 742473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 7425627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 7426b4e61e064b59e8076df81b061add9fb358fd2ed9Dmitri Plotnikov 7427d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 7428f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static boolean readBooleanQueryParameter(Uri uri, String parameter, 7429f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean defaultValue) { 7430f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7431f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // Manually parse the query, which is much faster than calling uri.getQueryParameter 7432f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 7433f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 7434f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 7435f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7436f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7437f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = query.indexOf(parameter); 7438f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 7439f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 7440f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7441f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7442f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameter.length(); 7443f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7444f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return !matchQueryParameter(query, index, "=0", false) 7445f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && !matchQueryParameter(query, index, "=false", true); 7446f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7447f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7448f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private static boolean matchQueryParameter(String query, int index, String value, 7449f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean ignoreCase) { 7450f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int length = value.length(); 7451f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return query.regionMatches(ignoreCase, index, value, 0, length) 7452f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && (query.length() == index + length || query.charAt(index + length) == '&'); 7453f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7454f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7455f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /** 7456f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * A fast re-implementation of {@link Uri#getQueryParameter} 7457f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov */ 7458f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static String getQueryParameter(Uri uri, String parameter) { 7459f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 7460f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 7461f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 7462f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7463f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7464f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int queryLength = query.length(); 7465f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int parameterLength = parameter.length(); 7466f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7467f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String value; 7468f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = 0; 7469f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov while (true) { 7470f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index = query.indexOf(parameter, index); 7471f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 7472f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 74735fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa } 74745fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa 74755fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // Should match against the whole parameter instead of its suffix. 74765fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // e.g. The parameter "param" must not be found in "some_param=val". 74775fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa if (index > 0) { 74785fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa char prevChar = query.charAt(index - 1); 74795fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa if (prevChar != '?' && prevChar != '&') { 74805fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa // With "some_param=val1¶m=val2", we should find second "param" occurrence. 74815fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa index += parameterLength; 74825fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa continue; 74835fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa } 7484f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7485f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7486f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameterLength; 7487f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7488f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (queryLength == index) { 7489f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 7490f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7491f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7492f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query.charAt(index) == '=') { 7493f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index++; 7494f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov break; 7495f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7496f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7497f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7498f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int ampIndex = query.indexOf('&', index); 7499f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (ampIndex == -1) { 7500f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index); 7501f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 7502f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index, ampIndex); 7503f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 7504f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 7505f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return Uri.decode(value); 7506f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 75075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 75080dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov protected boolean isAggregationUpgradeNeeded() { 75090dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 75100dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return false; 75110dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 75120dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 75135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro int version = Integer.parseInt(mContactsHelper.getProperty( 75145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro PROPERTY_AGGREGATION_ALGORITHM, "1")); 75150dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return version < PROPERTY_AGGREGATION_ALGORITHM_VERSION; 75160dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 75170dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 7518bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected void upgradeAggregationAlgorithmInBackground() { 75190dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov // This upgrade will affect very few contacts, so it can be performed on the 75200dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov // main thread during the initial boot after an OTA 75210dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 75220dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Log.i(TAG, "Upgrading aggregation algorithm"); 75230dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov int count = 0; 75240dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long start = SystemClock.currentThreadTimeMillis(); 75255d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro SQLiteDatabase db = null; 75260dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov try { 75275d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro switchToContactMode(); 75285d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db = mContactsHelper.getWritableDatabase(); 75295d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.set(db); 75305d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.beginTransaction(); 75315d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro Cursor cursor = db.query(true, 75320dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Tables.RAW_CONTACTS + " r1 JOIN " + Tables.RAW_CONTACTS + " r2", 75330dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov new String[]{"r1." + RawContacts._ID}, 75340dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov "r1." + RawContacts._ID + "!=r2." + RawContacts._ID + 75350dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.CONTACT_ID + "=r2." + RawContacts.CONTACT_ID + 75360dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov " AND r1." + RawContacts.ACCOUNT_NAME + "=r2." + RawContacts.ACCOUNT_NAME + 753743368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND r1." + RawContacts.ACCOUNT_TYPE + "=r2." + RawContacts.ACCOUNT_TYPE + 753843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro " AND r1." + RawContacts.DATA_SET + "=r2." + RawContacts.DATA_SET, 75390dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov null, null, null, null, null); 75400dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov try { 75410dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov while (cursor.moveToNext()) { 75420dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long rawContactId = cursor.getLong(0); 75430dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, 75440dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 75450dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov count++; 75460dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 75470dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } finally { 75480dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov cursor.close(); 75490dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 75505d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactAggregator.aggregateInTransaction(mTransactionContext.get(), db); 7551bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov updateSearchIndexInTransaction(); 75525d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.setTransactionSuccessful(); 75535d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mContactsHelper.setProperty(PROPERTY_AGGREGATION_ALGORITHM, 75540dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov String.valueOf(PROPERTY_AGGREGATION_ALGORITHM_VERSION)); 75550dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } finally { 75565d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro if (db != null) { 75575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro db.endTransaction(); 75585d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro } 75590dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov long end = SystemClock.currentThreadTimeMillis(); 75600dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov Log.i(TAG, "Aggregation algorithm upgraded for " + count 75610dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov + " contacts, in " + (end - start) + "ms"); 75620dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 75630dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 75649a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 75659a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov /* Visible for testing */ 75669a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov boolean isPhone() { 75679a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (!sIsPhoneInitialized) { 75689a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sIsPhone = new TelephonyManager(getContext()).isVoiceCapable(); 75699a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov sIsPhoneInitialized = true; 75709a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 75719a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return sIsPhone; 75729a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 757346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 757446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private boolean handleDataUsageFeedback(Uri uri) { 757546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final long currentTimeMillis = System.currentTimeMillis(); 757646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String usageType = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 757746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] ids = uri.getLastPathSegment().trim().split(","); 757846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final ArrayList<Long> dataIds = new ArrayList<Long>(); 757946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 758046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa for (String id : ids) { 758146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa dataIds.add(Long.valueOf(id)); 758246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 758346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final boolean successful; 758446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (TextUtils.isEmpty(usageType)) { 758546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Log.w(TAG, "Method for data usage feedback isn't specified. Ignoring."); 758646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa successful = false; 758746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 758846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa successful = updateDataUsageStat(dataIds, usageType, currentTimeMillis) > 0; 758946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 759046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 759146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa // Handle old API. This doesn't affect the result of this entire method. 759246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] questionMarks = new String[ids.length]; 759346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Arrays.fill(questionMarks, "?"); 759446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String where = Data._ID + " IN (" + TextUtils.join(",", questionMarks) + ")"; 75955d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final Cursor cursor = mActiveDb.get().query( 7596ed6bfd922fd84db21de08c1d12e93c501b86560dDaniel Lehmann Views.DATA, 759746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { Data.CONTACT_ID }, 759846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa where, ids, null, null, null); 759946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 760046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa while (cursor.moveToNext()) { 760146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa mSelectionArgs1[0] = cursor.getString(0); 760246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa ContentValues values2 = new ContentValues(); 760346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values2.put(Contacts.LAST_TIME_CONTACTED, currentTimeMillis); 76045d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().update(Tables.CONTACTS, values2, Contacts._ID + "=?", 76055d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mSelectionArgs1); 76065d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 76075d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 760846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 760946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 761046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa cursor.close(); 761146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 761246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 761346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return successful; 761446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 761546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 761646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 761746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Update {@link Tables#DATA_USAGE_STAT}. 761846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * 761946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * @return the number of rows affected. 762046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 7621f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa @VisibleForTesting 7622f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa /* package */ int updateDataUsageStat( 7623f9648a03e88e2d1a91c616a20d903e4c9a2468e5Daisuke Miyakawa List<Long> dataIds, String type, long currentTimeMillis) { 762446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final int typeInt = sDataUsageTypeMap.get(type); 762546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String where = DataUsageStatColumns.DATA_ID + " =? AND " 762646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa + DataUsageStatColumns.USAGE_TYPE_INT + " =?"; 762746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] columns = 762846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { DataUsageStatColumns._ID, DataUsageStatColumns.TIMES_USED }; 762946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final ContentValues values = new ContentValues(); 763046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa for (Long dataId : dataIds) { 763146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String[] args = new String[] { dataId.toString(), String.valueOf(typeInt) }; 76325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().beginTransaction(); 763346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 76345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro final Cursor cursor = mActiveDb.get().query(Tables.DATA_USAGE_STAT, columns, where, 76355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro args, null, null, null); 763646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa try { 763746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (cursor.getCount() > 0) { 763846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!cursor.moveToFirst()) { 763946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa Log.e(TAG, 764046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa "moveToFirst() failed while getAccount() returned non-zero."); 764146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 764246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.clear(); 764346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.TIMES_USED, cursor.getInt(1) + 1); 764446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.LAST_TIME_USED, currentTimeMillis); 76455d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().update(Tables.DATA_USAGE_STAT, values, 764646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DataUsageStatColumns._ID + " =?", 764746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa new String[] { cursor.getString(0) }); 764846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 764946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 765046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.clear(); 765146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.DATA_ID, dataId); 765246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.USAGE_TYPE_INT, typeInt); 765346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.TIMES_USED, 1); 765446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa values.put(DataUsageStatColumns.LAST_TIME_USED, currentTimeMillis); 76555d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().insert(Tables.DATA_USAGE_STAT, null, values); 765646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 76575d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().setTransactionSuccessful(); 765846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 765946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa cursor.close(); 766046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 766146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } finally { 76625d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro mActiveDb.get().endTransaction(); 766346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 766446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 766546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 766646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return dataIds.size(); 766746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 766846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 766946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa /** 767046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * Returns a sort order String for promoting data rows (email addresses, phone numbers, etc.) 767146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * associated with a primary account. The primary account should be supplied from applications 767246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * with {@link ContactsContract#PRIMARY_ACCOUNT_NAME} and 767346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * {@link ContactsContract#PRIMARY_ACCOUNT_TYPE}. Null will be returned when the primary 767446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa * account isn't available. 767546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa */ 767646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa private String getAccountPromotionSortOrder(Uri uri) { 767746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String primaryAccountName = 767846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa uri.getQueryParameter(ContactsContract.PRIMARY_ACCOUNT_NAME); 767946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa final String primaryAccountType = 768046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa uri.getQueryParameter(ContactsContract.PRIMARY_ACCOUNT_TYPE); 768146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa 768246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa // Data rows associated with primary account should be promoted. 768346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(primaryAccountName)) { 768446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa StringBuilder sb = new StringBuilder(); 768546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append("(CASE WHEN " + RawContacts.ACCOUNT_NAME + "="); 768646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DatabaseUtils.appendEscapedSQLString(sb, primaryAccountName); 768746abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa if (!TextUtils.isEmpty(primaryAccountType)) { 768846abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" AND " + RawContacts.ACCOUNT_TYPE + "="); 768946abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa DatabaseUtils.appendEscapedSQLString(sb, primaryAccountType); 769046abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 769146abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa sb.append(" THEN 0 ELSE 1 END)"); 769246abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return sb.toString(); 769346abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } else { 769446abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa return null; 769546abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 769646abbb56764add30cb6e6506f55d8dededc88113Daisuke Miyakawa } 76974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 7698