ContactsProvider2.java revision 4da1b8ded4435a3392bac3511c67182015e0953f
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.internal.content.SyncStateContentProviderHelper; 2053214b3ed12b0ff9cb589b6559311f2ac142f2e3Bjorn Bringertimport com.android.providers.contacts.ContactLookupKey.LookupKeySegment; 215b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns; 2297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns; 2397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Clauses; 2497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsColumns; 2597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsStatusUpdatesColumns; 2697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; 2797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DisplayNameSources; 2897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns; 2997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns; 3097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns; 3197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType; 3297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NicknameLookupColumns; 3397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneColumns; 3497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns; 3597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns; 3603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns; 3797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.SettingsColumns; 3897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns; 3997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 4097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.google.android.collect.Lists; 4197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.google.android.collect.Maps; 4297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport com.google.android.collect.Sets; 4397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 4497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.accounts.Account; 4597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.accounts.AccountManager; 46b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.OnAccountsUpdateListener; 47caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikovimport android.app.SearchManager; 485b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanaimport android.content.ContentProviderOperation; 49bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.content.ContentProviderResult; 50bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.content.ContentResolver; 51bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.content.ContentUris; 52c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.content.ContentValues; 53568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.Context; 54568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.Entity; 556ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.content.EntityIterator; 5635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.IContentService; 5767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.OperationApplicationException; 5867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.SharedPreferences; 59627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.SyncAdapterType; 60bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.content.UriMatcher; 61568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.SharedPreferences.Editor; 623d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.res.AssetFileDescriptor; 63627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.database.CharArrayBuffer; 6467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.database.Cursor; 65f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringertimport android.database.DatabaseUtils; 66e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException; 674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteContentHelper; 68e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikovimport android.database.sqlite.SQLiteCursor; 69ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.database.sqlite.SQLiteDatabase; 70ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.sqlite.SQLiteQueryBuilder; 7109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.sqlite.SQLiteStatement; 7209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.net.Uri; 734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.os.Bundle; 7408ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwoodimport android.os.MemoryFile; 754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.os.RemoteException; 764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.os.SystemProperties; 77d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikovimport android.pim.vcard.VCardComposer; 78bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.preference.PreferenceManager; 796ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.provider.BaseColumns; 80bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.provider.ContactsContract; 81bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.provider.LiveFolders; 82bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.provider.OpenableColumns; 83ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringertimport android.provider.SyncStateContract; 84bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 85b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.Contacts; 8615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikovimport android.provider.ContactsContract.Data; 870dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikovimport android.provider.ContactsContract.Groups; 880e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.provider.ContactsContract.PhoneLookup; 893d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 90508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.ContactsContract.Settings; 913de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 92b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.BaseTypes; 9397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email; 9497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 9597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 9697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 976d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 9897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone; 9997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 10097fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 10197fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 10297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport android.telephony.PhoneNumberUtils; 103ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.text.TextUtils; 1043de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.text.util.Rfc822Token; 1055b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikovimport android.text.util.Rfc822Tokenizer; 1063de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.util.Log; 107d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 1083de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport java.io.ByteArrayOutputStream; 109bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport java.io.FileNotFoundException; 1103de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport java.io.IOException; 11109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport java.io.OutputStream; 1123de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport java.lang.ref.SoftReference; 113916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikovimport java.util.ArrayList; 1143de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport java.util.BitSet; 11582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport java.util.Collections; 11697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport java.util.HashMap; 11797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport java.util.HashSet; 11897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikovimport java.util.List; 119a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport java.util.Locale; 1209a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikovimport java.util.Map; 121a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport java.util.Set; 122c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 124108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa/** 125d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Contacts content provider. The contract between this provider and applications 126b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov * is defined in {@link ContactsContract}. 127d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 128d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeypublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener { 129108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa 130108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa private static final String TAG = "ContactsProvider"; 13142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 1327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 13442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 135b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // TODO: check for restricted flag during insert(), update(), and delete() calls 1360e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 1375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 138622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private static final int DEFAULT_MAX_SUGGESTIONS = 5; 139b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1400e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff /** 141ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov * Shared preference key for the legacy contact import version. The need for a version 1424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * we can trigger re-import by incrementing the import version. 1444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 1454f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final String PREF_CONTACTS_IMPORTED = "contacts_imported_v1"; 1464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final int PREF_CONTACTS_IMPORT_VERSION = 1; 1475b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintana 148caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 149bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 150bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 151bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 1524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final String TIMES_CONTACED_SORT_COLUMN = "times_contacted_sort"; 15315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 15415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 15515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov + TIMES_CONTACED_SORT_COLUMN + " DESC, " 15615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 15715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov private static final String STREQUENT_LIMIT = 15815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 15905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 16005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 16105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int CONTACTS = 1000; 16205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 163619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private static final int CONTACTS_LOOKUP = 1002; 1643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 1653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int CONTACTS_DATA = 1004; 1663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 1673d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 168b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 1693d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 1703d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final int CONTACTS_PHOTO = 1009; 1713d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final int CONTACTS_AS_VCARD = 1010; 172b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov 173b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final int RAW_CONTACTS = 2002; 17451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 1753d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 1760dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static final int RAW_CONTACT_ENTITY_ID = 2005; 1770dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 1780dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static final int DATA = 3000; 1790e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final int DATA_ID = 3001; 1800e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final int PHONES = 3002; 181a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final int PHONES_ID = 3003; 1824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final int PHONES_FILTER = 3004; 183dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov private static final int EMAILS = 3005; 1845e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final int EMAILS_ID = 3006; 185d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 186dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov private static final int EMAILS_FILTER = 3008; 1879b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi private static final int POSTALS = 3009; 188d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final int POSTALS_ID = 3010; 189d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 190d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 191d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1926e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori private static final int AGGREGATION_EXCEPTIONS = 6000; 1939b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori private static final int AGGREGATION_EXCEPTION_ID = 6001; 1949b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 1959b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori private static final int STATUS_UPDATES = 7000; 1969b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori private static final int STATUS_UPDATES_ID = 7001; 1976e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori 1989b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori private static final int AGGREGATION_SUGGESTIONS = 8000; 1999b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 2009b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori private static final int SETTINGS = 9000; 2019b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 202de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa private static final int GROUPS = 10000; 203de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa private static final int GROUPS_ID = 10001; 2043716f1447ceb21180d1301790eabd8b9453f486dDave Santoro private static final int GROUPS_SUMMARY = 10003; 2053716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 2063716f1447ceb21180d1301790eabd8b9453f486dDave Santoro private static final int SYNCSTATE = 11000; 2073716f1447ceb21180d1301790eabd8b9453f486dDave Santoro private static final int SYNCSTATE_ID = 11001; 208d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 209d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 2105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 2115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 212a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 2135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 2145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 2155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 2165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 217a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int RAW_CONTACT_ENTITIES = 15001; 218f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 21942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann private interface DataContactsQuery { 2202149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov public static final String TABLE = "data " 2212149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 222a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 223a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 224a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov public static final String[] PROJECTION = new String[] { 2254f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton RawContactsColumns.CONCRETE_ID, 2265ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov DataColumns.CONCRETE_ID, 2275ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov ContactsColumns.CONCRETE_ID 2285ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov }; 22946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 2304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public static final int RAW_CONTACT_ID = 0; 2316bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov public static final int DATA_ID = 1; 2326bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov public static final int CONTACT_ID = 2; 233ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 23448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 23548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private interface DataDeleteQuery { 23648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 23748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 23848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov public static final String[] CONCRETE_COLUMNS = new String[] { 23948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov DataColumns.CONCRETE_ID, 24048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov MimetypesColumns.MIMETYPE, 24148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov Data.RAW_CONTACT_ID, 242a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton Data.IS_PRIMARY, 2436bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov Data.DATA1, 2446bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov }; 245b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 246b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 247b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov Data._ID, 24882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov MimetypesColumns.MIMETYPE, 24982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.RAW_CONTACT_ID, 2501f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Data.IS_PRIMARY, 25131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov Data.DATA1, 25231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov }; 253eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 254eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey public static final int _ID = 0; 255ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int MIMETYPE = 1; 256ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int RAW_CONTACT_ID = 2; 257ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int IS_PRIMARY = 3; 258ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int DATA1 = 4; 25935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana } 260b5a4add17815167d20a90645779df34cdf45280dFred Quintana 26135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private interface DataUpdateQuery { 262c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String[] COLUMNS = { Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE }; 263c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 264c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int _ID = 0; 2651b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov int RAW_CONTACT_ID = 1; 2661b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov int MIMETYPE = 2; 2671b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov } 2681b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 2691b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 27046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private interface RawContactsQuery { 27146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana String TABLE = Tables.RAW_CONTACTS; 27209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 27309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov String[] COLUMNS = new String[] { 274d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov RawContacts.DELETED, 275d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 276d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 2777a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov }; 2787a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 279dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana int DELETED = 0; 280dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana int ACCOUNT_TYPE = 1; 281dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana int ACCOUNT_NAME = 2; 282dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 283dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 284dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 285dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana public static final String FEATURE_LEGACY_HOSTED_OR_GOOGLE = "legacy_hosted_or_google"; 286dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 287dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana /** Sql where statement for filtering on groups. */ 288dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String CONTACTS_IN_GROUP_SELECT = 289dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Contacts._ID + " IN " 290dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "(SELECT " + RawContacts.CONTACT_ID 291dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " FROM " + Tables.RAW_CONTACTS 292dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 293dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 294dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " FROM " + Tables.DATA_JOIN_MIMETYPES 295dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 296dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 297dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "(SELECT " + Tables.GROUPS + "." + Groups._ID 298dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " FROM " + Tables.GROUPS 299dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " WHERE " + Groups.TITLE + "=?)))"; 300dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 301dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana /** Sql for updating DIRTY flag on multiple raw contacts */ 302dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String UPDATE_RAW_CONTACT_SET_DIRTY_SQL = 303dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana "UPDATE " + Tables.RAW_CONTACTS + 304dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana " SET " + RawContacts.DIRTY + "=1" + 305dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana " WHERE " + RawContacts._ID + " IN ("; 306e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov 307e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov /** Sql for updating VERSION on multiple raw contacts */ 308e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_VERSION_SQL = 309e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 310e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + 311e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 312e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov 313e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov /** Contains just BaseColumns._COUNT */ 314e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private static final HashMap<String, String> sCountProjectionMap; 315e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov /** Contains just the contacts columns */ 316e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private static final HashMap<String, String> sContactsProjectionMap; 317e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov /** Used for pushing starred contacts to the top of a times contacted list **/ 318e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private static final HashMap<String, String> sStrequentStarredProjectionMap; 319e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private static final HashMap<String, String> sStrequentFrequentProjectionMap; 320e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov /** Contains just the contacts vCard columns */ 321e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private static final HashMap<String, String> sContactsVCardProjectionMap; 322e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov /** Contains just the raw contacts columns */ 323e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 324e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov /** Contains the columns from the raw contacts entity view*/ 325e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private static final HashMap<String, String> sRawContactsEntityProjectionMap; 326e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov /** Contains columns from the data view */ 327e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private static final HashMap<String, String> sDataProjectionMap; 328e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov /** Contains columns from the data view */ 329e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private static final HashMap<String, String> sDistinctDataProjectionMap; 330e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov /** Contains the data and contacts columns, for joined tables */ 331e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private static final HashMap<String, String> sPhoneLookupProjectionMap; 332e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov /** Contains the just the {@link Groups} columns */ 333e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private static final HashMap<String, String> sGroupsProjectionMap; 334e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov /** Contains {@link Groups} columns along with summary details */ 335e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private static final HashMap<String, String> sGroupsSummaryProjectionMap; 336e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov /** Contains the agg_exceptions columns */ 337e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 338e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov /** Contains the agg_exceptions columns */ 339d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sSettingsProjectionMap; 340f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov /** Contains StatusUpdates columns */ 341f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private static final HashMap<String, String> sStatusUpdatesProjectionMap; 342f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov /** Contains Live Folders columns */ 34367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final HashMap<String, String> sLiveFoldersProjectionMap; 34467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 3456cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // where clause to update the status_updates table 3463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 347f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 348ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 349ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 350d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 35167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey /** Precompiled sql statement for setting a data record to the primary. */ 352d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private SQLiteStatement mSetPrimaryStatement; 353ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Precompiled sql statement for setting a data record to the super primary. */ 3541f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private SQLiteStatement mSetSuperPrimaryStatement; 355f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov /** Precompiled sql statement for incrementing times contacted for a contact */ 35619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private SQLiteStatement mContactsLastTimeContactedUpdate; 35719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka /** Precompiled sql statement for updating a contact display name */ 35819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private SQLiteStatement mRawContactDisplayNameUpdate; 359ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov /** Precompiled sql statement for updating an aggregated status update */ 360ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private SQLiteStatement mLastStatusUpdate; 361ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private SQLiteStatement mNameLookupInsert; 36219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private SQLiteStatement mNameLookupDelete; 36319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private SQLiteStatement mStatusUpdateAutoTimestamp; 36419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private SQLiteStatement mStatusUpdateInsert; 365ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private SQLiteStatement mStatusUpdateReplace; 366ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private SQLiteStatement mStatusAttributionUpdate; 36719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private SQLiteStatement mStatusUpdateDelete; 36819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 369c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache private long mMimeTypeIdEmail; 370caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov private long mMimeTypeIdIm; 37171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private long mMimeTypeIdStructuredName; 37271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private long mMimeTypeIdOrganization; 37371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private long mMimeTypeIdNickname; 37471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private long mMimeTypeIdPhone; 37571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 37671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 37771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private String[] mSelectionArgs2 = new String[2]; 37871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private String[] mSelectionArgs3 = new String[3]; 37971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private Account mAccount; 38071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 38171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov static { 38271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov // Contacts URI matching table 38371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov final UriMatcher matcher = sUriMatcher; 38471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 385a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 386a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 387a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 388a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov AGGREGATION_SUGGESTIONS); 389a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 390a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov AGGREGATION_SUGGESTIONS); 391a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_PHOTO); 392a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 393a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 394a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 395a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 396a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 397c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 398c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov CONTACTS_STREQUENT_FILTER); 399c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 400c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 401c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 402c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 403c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 404c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 405c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 406c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 407c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 408c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 409c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 410c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 411c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 412c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 413c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 414c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 415c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 416c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 417c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 418c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 419c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 420c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 421c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov 422c918b0d3ab17a45a392748f43956b927c83eb402Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 423916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 424916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 425916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 426916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 42792ddc5cdc4d89ee2c6e861ae7b3a3a913ffa0100Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 428916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov SYNCSTATE_ID); 429f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov 430f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 431f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 432f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 433f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 434f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 435f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov 436f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 437f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov 438f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 439f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 440f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov 441f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 442f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov SEARCH_SUGGESTIONS); 443f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 444916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov SEARCH_SUGGESTIONS); 445f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/#", 446f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov SEARCH_SHORTCUT); 447f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 448f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 449f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 450f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 451f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 452f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 453f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 454f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 455f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 4563d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov } 4573d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov 458f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov static { 459f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sCountProjectionMap = new HashMap<String, String>(); 460f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*)"); 461f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 462f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sContactsProjectionMap = new HashMap<String, String>(); 463cf832869bcf91b8037d8b7f510a3a213b30764a3Dmitri Plotnikov sContactsProjectionMap.put(Contacts._ID, Contacts._ID); 464f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 465f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sContactsProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 466f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sContactsProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 467f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sContactsProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 468f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sContactsProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 469f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sContactsProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 470f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sContactsProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 471f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sContactsProjectionMap.put(Contacts.HAS_PHONE_NUMBER, Contacts.HAS_PHONE_NUMBER); 472f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sContactsProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 473f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sContactsProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 474f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 475f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // Handle projections for Contacts-level statuses 476f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sContactsProjectionMap, Contacts.CONTACT_PRESENCE, 477f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 478f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS, 479f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS); 480f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 481f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 482f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 483f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 48403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_LABEL, 485f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 486f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_ICON, 487f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 488f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 489f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sStrequentStarredProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 490f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sStrequentStarredProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 491f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Long.MAX_VALUE + " AS " + TIMES_CONTACED_SORT_COLUMN); 492f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 493f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sStrequentFrequentProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 494f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sStrequentFrequentProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 495f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Contacts.TIMES_CONTACTED + " AS " + TIMES_CONTACED_SORT_COLUMN); 496f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 497f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sContactsVCardProjectionMap = Maps.newHashMap(); 498f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sContactsVCardProjectionMap.put(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME 499f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " || '.vcf' AS " + OpenableColumns.DISPLAY_NAME); 500f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sContactsVCardProjectionMap.put(OpenableColumns.SIZE, "0 AS " + OpenableColumns.SIZE); 501f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 502f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap = new HashMap<String, String>(); 503f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts._ID, RawContacts._ID); 504f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 505f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 506f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 507f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 508f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 509f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 510f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DELETED, RawContacts.DELETED); 511f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.TIMES_CONTACTED, RawContacts.TIMES_CONTACTED); 512f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.LAST_TIME_CONTACTED, 513f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov RawContacts.LAST_TIME_CONTACTED); 514f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CUSTOM_RINGTONE, RawContacts.CUSTOM_RINGTONE); 515f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SEND_TO_VOICEMAIL, RawContacts.SEND_TO_VOICEMAIL); 516f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.STARRED, RawContacts.STARRED); 517f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE); 518f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC1, RawContacts.SYNC1); 519f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC2, RawContacts.SYNC2); 520f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC3, RawContacts.SYNC3); 521f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC4, RawContacts.SYNC4); 522f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 523f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap = new HashMap<String, String>(); 524f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data._ID, Data._ID); 525f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 526f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 527f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 528f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 529f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 530f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 531f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.DATA1, Data.DATA1); 532f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.DATA2, Data.DATA2); 533f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.DATA3, Data.DATA3); 534f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.DATA4, Data.DATA4); 535f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.DATA5, Data.DATA5); 536f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.DATA6, Data.DATA6); 537f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.DATA7, Data.DATA7); 538f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.DATA8, Data.DATA8); 539f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.DATA9, Data.DATA9); 540f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.DATA10, Data.DATA10); 541f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.DATA11, Data.DATA11); 542f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.DATA12, Data.DATA12); 543f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.DATA13, Data.DATA13); 544f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.DATA14, Data.DATA14); 545f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.DATA15, Data.DATA15); 546f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 547f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 548f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 549f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 550f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Data.CONTACT_ID, Data.CONTACT_ID); 551f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 552f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 553f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 554f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 555f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 556f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 557f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 558038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 559f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 560f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 561f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 562f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 563e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 564f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 565f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 566f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 567f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov HashMap<String, String> columns; 568f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns = new HashMap<String, String>(); 569f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(RawContacts._ID, RawContacts._ID); 570f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 571f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 572916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov columns.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 573f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 574f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(RawContacts.VERSION, RawContacts.VERSION); 575f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(RawContacts.DIRTY, RawContacts.DIRTY); 576f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(RawContacts.DELETED, RawContacts.DELETED); 577916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov columns.put(RawContacts.IS_RESTRICTED, RawContacts.IS_RESTRICTED); 5785e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar columns.put(RawContacts.SYNC1, RawContacts.SYNC1); 579f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(RawContacts.SYNC2, RawContacts.SYNC2); 580f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(RawContacts.SYNC3, RawContacts.SYNC3); 581f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(RawContacts.SYNC4, RawContacts.SYNC4); 582f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 583f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.MIMETYPE, Data.MIMETYPE); 584f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.DATA1, Data.DATA1); 585f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.DATA2, Data.DATA2); 586f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.DATA3, Data.DATA3); 587f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.DATA4, Data.DATA4); 588f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.DATA5, Data.DATA5); 589f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey columns.put(Data.DATA6, Data.DATA6); 590f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.DATA7, Data.DATA7); 591f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.DATA8, Data.DATA8); 592f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.DATA9, Data.DATA9); 593f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.DATA10, Data.DATA10); 594f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.DATA11, Data.DATA11); 595ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov columns.put(Data.DATA12, Data.DATA12); 596f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.DATA13, Data.DATA13); 597f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.DATA14, Data.DATA14); 598f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.DATA15, Data.DATA15); 599f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.SYNC1, Data.SYNC1); 600f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.SYNC2, Data.SYNC2); 601f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.SYNC3, Data.SYNC3); 602f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.SYNC4, Data.SYNC4); 603f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(RawContacts.Entity.DATA_ID, RawContacts.Entity.DATA_ID); 604f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.STARRED, Data.STARRED); 605f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.DATA_VERSION, Data.DATA_VERSION); 606f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 607f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 608f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 609f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sRawContactsEntityProjectionMap = columns; 610f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 611f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // Handle projections for Contacts-level statuses 612f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDataProjectionMap, Contacts.CONTACT_PRESENCE, 613f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 614f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS, 615f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS); 616f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 617a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 618f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 619f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 620f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 621f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 622f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 623f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 624f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 625f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // Handle projections for Data-level statuses 626f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDataProjectionMap, Data.PRESENCE, 627f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 628f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDataProjectionMap, Data.STATUS, 629f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov StatusUpdatesColumns.CONCRETE_STATUS); 630a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov addProjection(sDataProjectionMap, Data.STATUS_TIMESTAMP, 631f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 632f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDataProjectionMap, Data.STATUS_RES_PACKAGE, 633f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 634f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDataProjectionMap, Data.STATUS_LABEL, 635f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 636f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDataProjectionMap, Data.STATUS_ICON, 637f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov StatusUpdatesColumns.CONCRETE_STATUS_ICON); 638f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 639f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // Projection map for data grouped by contact (not raw contact) and some data field(s) 640f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap = new HashMap<String, String>(); 641f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data._ID, 642f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov "MIN(" + Data._ID + ") AS " + Data._ID); 643f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 644f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 645f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 646f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 6474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 648f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA1, Data.DATA1); 649f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA2, Data.DATA2); 650f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA3, Data.DATA3); 651f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA4, Data.DATA4); 652f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA5, Data.DATA5); 653f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA6, Data.DATA6); 654f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA7, Data.DATA7); 655f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA8, Data.DATA8); 656f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA9, Data.DATA9); 657f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA10, Data.DATA10); 658f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA11, Data.DATA11); 659f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA12, Data.DATA12); 6605e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA13, Data.DATA13); 661f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA14, Data.DATA14); 662f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA15, Data.DATA15); 663f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 664f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 665f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 666f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 667f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 668f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 669f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 6709261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana sDistinctDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 671f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 672f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 673f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 674f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 675f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 676f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 677f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sDistinctDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, 678f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov GroupMembership.GROUP_SOURCE_ID); 679f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 6803d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov // Handle projections for Contacts-level statuses 6813d67ff829e8acb0f650f155c3c0d377c0f46507aDmitri Plotnikov addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_PRESENCE, 682f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 683f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS, 684f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS); 685f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 686f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 687f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 6882530512f639c4979fd7371c7dd25dd67e8118124Bai Tao ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 689f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 690f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 691ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 692f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 693f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 694f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // Handle projections for Data-level statuses 695f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDistinctDataProjectionMap, Data.PRESENCE, 696f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 697f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDistinctDataProjectionMap, Data.STATUS, 698f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov StatusUpdatesColumns.CONCRETE_STATUS); 699f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDistinctDataProjectionMap, Data.STATUS_TIMESTAMP, 700f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 701f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDistinctDataProjectionMap, Data.STATUS_RES_PACKAGE, 702f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 703f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDistinctDataProjectionMap, Data.STATUS_LABEL, 704f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 705f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov addProjection(sDistinctDataProjectionMap, Data.STATUS_ICON, 706f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov StatusUpdatesColumns.CONCRETE_STATUS_ICON); 707f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 708f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sPhoneLookupProjectionMap = new HashMap<String, String>(); 709c039cfb78c40730483fd71178df63ada5826a315Dmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup._ID, 710f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsColumns.CONCRETE_ID + " AS " + PhoneLookup._ID); 711f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LOOKUP_KEY, 712f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Contacts.LOOKUP_KEY + " AS " + PhoneLookup.LOOKUP_KEY); 713f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.DISPLAY_NAME, 714f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsColumns.CONCRETE_DISPLAY_NAME + " AS " + PhoneLookup.DISPLAY_NAME); 715f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LAST_TIME_CONTACTED, 716ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContactsColumns.CONCRETE_LAST_TIME_CONTACTED 717f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AS " + PhoneLookup.LAST_TIME_CONTACTED); 718f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TIMES_CONTACTED, 719f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsColumns.CONCRETE_TIMES_CONTACTED + " AS " + PhoneLookup.TIMES_CONTACTED); 720f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.STARRED, 721f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsColumns.CONCRETE_STARRED + " AS " + PhoneLookup.STARRED); 722f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.IN_VISIBLE_GROUP, 723f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " AS " + PhoneLookup.IN_VISIBLE_GROUP); 724f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.PHOTO_ID, 725f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Contacts.PHOTO_ID + " AS " + PhoneLookup.PHOTO_ID); 726f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.CUSTOM_RINGTONE, 727f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsColumns.CONCRETE_CUSTOM_RINGTONE + " AS " + PhoneLookup.CUSTOM_RINGTONE); 728f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.HAS_PHONE_NUMBER, 729f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Contacts.HAS_PHONE_NUMBER + " AS " + PhoneLookup.HAS_PHONE_NUMBER); 730f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.SEND_TO_VOICEMAIL, 731f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL 732f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AS " + PhoneLookup.SEND_TO_VOICEMAIL); 733373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.NUMBER, 734f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Phone.NUMBER + " AS " + PhoneLookup.NUMBER); 735f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TYPE, 736f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Phone.TYPE + " AS " + PhoneLookup.TYPE); 737f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LABEL, 738f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov Phone.LABEL + " AS " + PhoneLookup.LABEL); 739f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 740f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // Groups projection map 741eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns = new HashMap<String, String>(); 742f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups._ID, Groups._ID); 743f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 744f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 745f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 746f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.DIRTY, Groups.DIRTY); 747f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.VERSION, Groups.VERSION); 748f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.RES_PACKAGE, Groups.RES_PACKAGE); 749f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.TITLE, Groups.TITLE); 750f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 751f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 752f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.SYSTEM_ID, Groups.SYSTEM_ID); 753f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.DELETED, Groups.DELETED); 754f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.NOTES, Groups.NOTES); 755f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.SHOULD_SYNC, Groups.SHOULD_SYNC); 756f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.SYNC1, Groups.SYNC1); 757f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.SYNC2, Groups.SYNC2); 758f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.SYNC3, Groups.SYNC3); 759f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.SYNC4, Groups.SYNC4); 760f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sGroupsProjectionMap = columns; 761f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 762f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // RawContacts and groups projection map 763f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns = new HashMap<String, String>(); 764f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.putAll(sGroupsProjectionMap); 765f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 766f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 767f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 768f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ") AS " + Groups.SUMMARY_COUNT); 769f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 770f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 771f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 772f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 773f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ") AS " + Groups.SUMMARY_WITH_PHONES); 774f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sGroupsSummaryProjectionMap = columns; 775f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 776f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // Aggregate exception projection map 777f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns = new HashMap<String, String>(); 778f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 77982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 780f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID1, AggregationExceptions.RAW_CONTACT_ID1); 781f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID2, AggregationExceptions.RAW_CONTACT_ID2); 782f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 783f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 784f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // Settings projection map 785f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns = new HashMap<String, String>(); 786f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Settings.ACCOUNT_NAME, Settings.ACCOUNT_NAME); 787f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Settings.ACCOUNT_TYPE, Settings.ACCOUNT_TYPE); 788f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Settings.UNGROUPED_VISIBLE, Settings.UNGROUPED_VISIBLE); 789f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Settings.SHOULD_SYNC, Settings.SHOULD_SYNC); 790f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Settings.ANY_UNSYNCED, "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 791f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ",(SELECT (CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL THEN 1 ELSE MIN(" 792f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + Groups.SHOULD_SYNC + ") END) FROM " + Tables.GROUPS + " WHERE " 793f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" + SettingsColumns.CONCRETE_ACCOUNT_NAME 794f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 795f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0 THEN 1 ELSE 0 END) AS " 796f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + Settings.ANY_UNSYNCED); 797f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(Settings.UNGROUPED_COUNT, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 798f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " GROUP BY " 799f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID + " HAVING " + Clauses.HAVING_NO_GROUPS 800f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + ")) AS " + Settings.UNGROUPED_COUNT); 8011b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov columns.put(Settings.UNGROUPED_WITH_PHONES, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 802f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " WHERE " 803f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + Contacts.HAS_PHONE_NUMBER + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 804f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + " HAVING " + Clauses.HAVING_NO_GROUPS + ")) AS " 805f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + Settings.UNGROUPED_WITH_PHONES); 806f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov sSettingsProjectionMap = columns; 807f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov 808f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns = new HashMap<String, String>(); 809f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(PresenceColumns.RAW_CONTACT_ID, PresenceColumns.RAW_CONTACT_ID); 810d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov columns.put(StatusUpdates.DATA_ID, 811f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov DataColumns.CONCRETE_ID + " AS " + StatusUpdates.DATA_ID); 812f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(StatusUpdates.IM_ACCOUNT, StatusUpdates.IM_ACCOUNT); 813f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(StatusUpdates.IM_HANDLE, StatusUpdates.IM_HANDLE); 814f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(StatusUpdates.PROTOCOL, StatusUpdates.PROTOCOL); 815f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 816f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov // properly enforce uniqueness of null values 817f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(StatusUpdates.CUSTOM_PROTOCOL, "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL 818f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + "='' THEN NULL ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END) AS " 819f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov + StatusUpdates.CUSTOM_PROTOCOL); 820778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov columns.put(StatusUpdates.PRESENCE, StatusUpdates.PRESENCE); 821778d92d4dce5f76c649e2aca9d00d3f214cd7643Dmitri Plotnikov columns.put(StatusUpdates.STATUS, StatusUpdates.STATUS); 822f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov columns.put(StatusUpdates.STATUS_TIMESTAMP, StatusUpdates.STATUS_TIMESTAMP); 8237e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(StatusUpdates.STATUS_RES_PACKAGE, StatusUpdates.STATUS_RES_PACKAGE); 8249705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori columns.put(StatusUpdates.STATUS_ICON, StatusUpdates.STATUS_ICON); 8259705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori columns.put(StatusUpdates.STATUS_LABEL, StatusUpdates.STATUS_LABEL); 8269705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori sStatusUpdatesProjectionMap = columns; 8279705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 8289705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // Live folder projection 8299705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori sLiveFoldersProjectionMap = new HashMap<String, String>(); 8302526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders._ID, 8312526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov Contacts._ID + " AS " + LiveFolders._ID); 832bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders.NAME, 833bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Contacts.DISPLAY_NAME + " AS " + LiveFolders.NAME); 834bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 835bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 83651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov // for contacts without a photo 83703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov // sLiveFoldersProjectionMap.put(LiveFolders.ICON_BITMAP, 83803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov // Photos.DATA + " AS " + LiveFolders.ICON_BITMAP); 83903197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 84003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 84103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov private static void addProjection(HashMap<String, String> map, String toField, String fromField) { 8429a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov map.put(toField, fromField + " AS " + toField); 8439a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 8449a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 845f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov /** 8461129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov * Handles inserts and update for a specific Data type. 8471129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov */ 8482526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private abstract class DataRowHandler { 8492526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 850f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov protected final String mMimetype; 851f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov protected long mMimetypeId; 8524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 8534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @SuppressWarnings("all") 854a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton public DataRowHandler(String mimetype) { 855d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov mMimetype = mimetype; 856d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 857a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov // To ensure the data column position. This is dead code if properly configured. 858a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (StructuredName.DISPLAY_NAME != Data.DATA1 || Nickname.NAME != Data.DATA1 8593653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov || Organization.COMPANY != Data.DATA1 || Phone.NUMBER != Data.DATA1 8603653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov || Email.DATA != Data.DATA1) { 8612d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov throw new AssertionError("Some of ContactsContract.CommonDataKinds class primary" 8622d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov + " data is not in DATA1 column"); 863a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 864c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov } 8655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 8665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov protected long getMimeTypeId() { 8672149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (mMimetypeId == 0) { 8685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov mMimetypeId = mDbHelper.getMimeTypeId(mMimetype); 8692149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 8702149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov return mMimetypeId; 871a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 872a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 873a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** 874a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * Inserts a row into the {@link Data} table. 875f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey */ 87642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 87742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final long dataId = db.insert(Tables.DATA, null, values); 8785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 879ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 880ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (primary != null && primary != 0) { 8815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 8823653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 8835ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 8845ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return dataId; 8855ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 88646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 88746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana /** 88846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana * Validates data and updates a {@link Data} row using the cursor, which contains 889b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov * the current data. 8904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 8914f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public void update(SQLiteDatabase db, ContentValues values, Cursor c, 892ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar boolean callerIsSyncAdapter) { 89348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 8945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 895ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 8964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (values.containsKey(Data.IS_SUPER_PRIMARY)) { 89748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 8981dac83b8fa58944acfd00f44e717a7dddc659d2dDmitri Plotnikov setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 8995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov setIsPrimary(rawContactId, dataId, mimeTypeId); 9005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 9014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 902ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar values.remove(Data.IS_SUPER_PRIMARY); 90348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 9041f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else if (values.containsKey(Data.IS_PRIMARY)) { 905ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey setIsPrimary(rawContactId, dataId, getMimeTypeId()); 906ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 907ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Now that we've taken care of setting this, remove it from "values". 908ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.remove(Data.IS_PRIMARY); 90935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana } 910b5a4add17815167d20a90645779df34cdf45280dFred Quintana 911b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (values.size() > 0) { 91235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana mSelectionArgs1[0] = String.valueOf(dataId); 913a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton mDb.update(Tables.DATA, values, Data._ID + " =?", mSelectionArgs1); 914b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 915b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 916b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov if (!callerIsSyncAdapter) { 917b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov setRawContactDirty(rawContactId); 9184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 919eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 920eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 92182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 92282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 9231f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 924c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 925c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 926c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=?", mSelectionArgs1); 927c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 9282d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill db.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=?", mSelectionArgs1); 929c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (count != 0 && primary) { 930c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov fixPrimary(db, rawContactId); 9311b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov } 9321b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov return count; 9331b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov } 9341b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 9351b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 9361b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov long mimeTypeId = getMimeTypeId(); 9371b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov long primaryId = -1; 9381b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov int primaryType = -1; 93909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 94009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov Cursor c = db.query(DataDeleteQuery.TABLE, 941d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov DataDeleteQuery.CONCRETE_COLUMNS, 942d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Data.RAW_CONTACT_ID + "=?" + 943d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov " AND " + DataColumns.MIMETYPE_ID + "=" + mimeTypeId, 9447a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov mSelectionArgs1, null, null, null); 9457a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov try { 94619a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov while (c.moveToNext()) { 94719a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 948d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA1); 949d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 950d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov primaryId = dataId; 951d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov primaryType = type; 952d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 953d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 954d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } finally { 955d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov c.close(); 956d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 9574458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov if (primaryId != -1) { 9584458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov setIsPrimary(rawContactId, primaryId, mimeTypeId); 959d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 9603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 961ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 962ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov /** 963ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 964e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov * row. Lower number represents higher priority. 965ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 966ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov protected int getTypeRank(int type) { 967ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return 0; 968ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 969ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 970a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov protected void fixRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 971e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov if (!isNewRawContact(rawContactId)) { 972e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov updateRawContactDisplayName(db, rawContactId); 973e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov mContactAggregator.updateDisplayName(db, rawContactId); 974e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov } 975e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov } 9763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 977b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov public boolean isAggregationRequired() { 97831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov return true; 9794097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov } 980f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 981315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov /** 982622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Return set of values, using current values at given {@link Data#_ID} 983622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * as baseline, but augmented with any updates. 98472e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov */ 985622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public ContentValues getAugmentedValues(SQLiteDatabase db, long dataId, 986f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov ContentValues update) { 987a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov final ContentValues values = new ContentValues(); 988d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 989f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov final Cursor cursor = db.query(Tables.DATA, null, Data._ID + "=?", 990a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mSelectionArgs1, null, null, null); 99120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 99273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (cursor.moveToFirst()) { 99320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < cursor.getColumnCount(); i++) { 99409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov final String key = cursor.getColumnName(i); 9953826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov values.put(key, cursor.getString(i)); 99609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 99715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 99815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } finally { 99915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov cursor.close(); 1000bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 100173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov values.putAll(update); 1002d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov return values; 1003de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 10041a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 10051a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 100681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 100781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 10084cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao public CustomDataRowHandler(String mimetype) { 10093826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov super(mimetype); 1010d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov } 1011bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1012bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1013bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 10144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private final NameSplitter mSplitter; 10154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1016de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov public StructuredNameRowHandler(NameSplitter splitter) { 1017ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 1018ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov mSplitter = splitter; 1019ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 1020ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov 1021ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov @Override 1022ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1023ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov fixStructuredNameComponents(values, values); 102435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1025ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 102615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 102715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 102815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 1029b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 103072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov return dataId; 1031a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov } 103265ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov 1033bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 103415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 103515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov boolean callerIsSyncAdapter) { 103672e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov final long dataId = c.getLong(DataUpdateQuery._ID); 1037bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1038bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1039bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final ContentValues augmented = getAugmentedValues(db, dataId, values); 1040bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov fixStructuredNameComponents(augmented, values); 1041bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1042bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov super.update(db, values, c, callerIsSyncAdapter); 1043bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1044bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (values.containsKey(StructuredName.DISPLAY_NAME)) { 1045bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 10462a0d5f9c628e723261bc5198e0fd606076b76b74Dmitri Plotnikov deleteNameLookup(dataId); 104715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name); 1048bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1049bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1050bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1051bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 105205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov @Override 1053bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 105415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 10553826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 105649d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov 10574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton int count = super.delete(db, c); 10584f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1059767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov deleteNameLookup(dataId); 106051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 106151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return count; 106204b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov } 106315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 106415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov /** 10654cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao * Specific list of structured fields. 106604b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov */ 10674cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao private final String[] STRUCTURED_FIELDS = new String[] { 10684cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 106951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov StructuredName.FAMILY_NAME, StructuredName.SUFFIX 1070cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao }; 10715b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 107215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov /** 10735b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov * Parses the supplied display name, but only if the incoming values do 1074f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov * not already contain structured name parts. Also, if the display name 10755b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov * is not provided, generate one by concatenating first name and last 1076bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * name. 1077bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov */ 1078bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private void fixStructuredNameComponents(ContentValues augmented, ContentValues update) { 10796d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov final String unstruct = update.getAsString(StructuredName.DISPLAY_NAME); 1080bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 10816d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 1082bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 10836d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov 1084bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (touchedUnstruct && !touchedStruct) { 10856d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1086bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mSplitter.split(name, unstruct); 10876d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov name.toValues(update); 1088bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } else if (!touchedUnstruct 10896d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 1090bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // We need to update the display name when any structured components 1091bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // are specified, even when they are null, which is why we are checking 10926d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov // areAnySpecified. The touchedStruct in the condition is an optimization: 1093bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // if there are non-null values, we know for a fact that some values are present. 1094bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 10956d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov name.fromValues(augmented); 1096bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final String joined = mSplitter.join(name); 1097bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov update.put(StructuredName.DISPLAY_NAME, joined); 10986d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov } 10996d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov } 11006d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov } 1101bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1102bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public class StructuredPostalRowHandler extends DataRowHandler { 1103bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private PostalSplitter mSplitter; 1104bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1105bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public StructuredPostalRowHandler(PostalSplitter splitter) { 1106bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov super(StructuredPostal.CONTENT_ITEM_TYPE); 1107bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mSplitter = splitter; 1108bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1109bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1110bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 1111bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1112bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov fixStructuredPostalComponents(values, values); 1113bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return super.insert(db, rawContactId, values); 1114bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1115bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1116bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 1117bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1118bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov boolean callerIsSyncAdapter) { 1119bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final long dataId = c.getLong(DataUpdateQuery._ID); 112015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov final ContentValues augmented = getAugmentedValues(db, dataId, values); 112115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov fixStructuredPostalComponents(augmented, values); 112215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov super.update(db, values, c, callerIsSyncAdapter); 112315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 112415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 112515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov /** 112615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov * Specific list of structured fields. 112715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov */ 1128bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private final String[] STRUCTURED_FIELDS = new String[] { 112915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov StructuredPostal.STREET, StructuredPostal.POBOX, StructuredPostal.NEIGHBORHOOD, 113015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov StructuredPostal.CITY, StructuredPostal.REGION, StructuredPostal.POSTCODE, 1131bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov StructuredPostal.COUNTRY, 1132bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov }; 1133bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1134bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /** 1135bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * Prepares the given {@link StructuredPostal} row, building 1136bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * {@link StructuredPostal#FORMATTED_ADDRESS} to match the structured 1137bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * values when missing. When structured components are missing, the 1138bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * unstructured value is assigned to {@link StructuredPostal#STREET}. 1139bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov */ 1140bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov private void fixStructuredPostalComponents(ContentValues augmented, ContentValues update) { 1141bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final String unstruct = update.getAsString(StructuredPostal.FORMATTED_ADDRESS); 1142bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 114315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 114415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 114515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 114615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov final PostalSplitter.Postal postal = new PostalSplitter.Postal(); 114715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 114815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov if (touchedUnstruct && !touchedStruct) { 114915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mSplitter.split(postal, unstruct); 1150bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov postal.toValues(update); 1151bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } else if (!touchedUnstruct 1152bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 1153bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov // See comment in 1154bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov postal.fromValues(augmented); 1155bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final String joined = mSplitter.join(postal); 1156bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov update.put(StructuredPostal.FORMATTED_ADDRESS, joined); 1157bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1158bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1159bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1160bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1161fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 1162fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1163fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov private final String mTypeColumn; 1164fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov private final String mLabelColumn; 1165fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1166bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 1167bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov super(mimetype); 1168bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mTypeColumn = typeColumn; 1169bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov mLabelColumn = labelColumn; 1170bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1171bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1172bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 117305e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 117405e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov enforceTypeAndLabel(values, values); 117505e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov return super.insert(db, rawContactId, values); 117605e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov } 117705e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov 1178bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov @Override 1179bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1180bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov boolean callerIsSyncAdapter) { 1181bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final long dataId = c.getLong(DataUpdateQuery._ID); 1182bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov final ContentValues augmented = getAugmentedValues(db, dataId, values); 1183bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov enforceTypeAndLabel(augmented, values); 1184bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov super.update(db, values, c, callerIsSyncAdapter); 1185bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1186bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1187bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov /** 1188bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * If the given {@link ContentValues} defines {@link #mTypeColumn}, 1189bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov * enforce that {@link #mLabelColumn} only appears when type is 11904cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao * {@link BaseTypes#TYPE_CUSTOM}. Exception is thrown otherwise. 11914cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao */ 119253fac8f99f3884c372c907a76766d27fa9e1d95fDmitri Plotnikov private void enforceTypeAndLabel(ContentValues augmented, ContentValues update) { 11933826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov final boolean hasType = !TextUtils.isEmpty(augmented.getAsString(mTypeColumn)); 11943826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov final boolean hasLabel = !TextUtils.isEmpty(augmented.getAsString(mLabelColumn)); 11954f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov 11964f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov if (hasLabel && !hasType) { 11974f20a360a2f0a7a83900c28fc7728542b38d8939Dmitri Plotnikov // When label exists, assert that some type is defined 1198fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov throw new IllegalArgumentException(mTypeColumn + " must be specified when " 11994cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao + mLabelColumn + " is defined."); 120051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 120151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 120251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 120351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 120451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 120551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 120651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov public OrganizationDataRowHandler() { 120751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 1208bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1209f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 1210f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov @Override 1211f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1212f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov String company = values.getAsString(Organization.COMPANY); 1213f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov String title = values.getAsString(Organization.TITLE); 1214f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 121551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 121651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 121751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 121851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov insertNameLookupForOrganization(rawContactId, dataId, company, title); 121951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return dataId; 122051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 122151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 122251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov @Override 122351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1224bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov boolean callerIsSyncAdapter) { 1225bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov String company = values.getAsString(Organization.COMPANY); 1226bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov String title = values.getAsString(Organization.TITLE); 1227bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 122851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1229fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1230fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov super.update(db, values, c, callerIsSyncAdapter); 1231fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1232fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1233fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov deleteNameLookup(dataId); 1234fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov insertNameLookupForOrganization(rawContactId, dataId, company, title); 1235fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1236fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1237fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov @Override 1238fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1239fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 1240fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1241fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1242fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov int count = super.delete(db, c); 1243fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1244fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov deleteNameLookup(dataId); 1245fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov return count; 1246fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov } 1247fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov 1248fd2a6a5b7ecbbec6298182daee3b252896f82ea4Dmitri Plotnikov @Override 124905e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov protected int getTypeRank(int type) { 125005e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov switch (type) { 125105e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov case Organization.TYPE_WORK: return 0; 125205e50fbf9809bf04eceec3d2a2753630dc4f9315Dmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 1253bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case Organization.TYPE_OTHER: return 2; 1254bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov default: return 1000; 125551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 125651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 12573826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 12583826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov @Override 12593826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov public boolean isAggregationRequired() { 12603826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return false; 12613826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 12623826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 12633826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 126449d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 126549d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov 12663826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov public EmailDataRowHandler() { 12673826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 12683826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 12693826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 12703826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov @Override 12713826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 127231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov String address = values.getAsString(Email.DATA); 1273de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 1274b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1275b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov 127631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 127731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 1278013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return dataId; 1279013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 1280013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 1281013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov @Override 12825df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 12835df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov boolean callerIsSyncAdapter) { 12845df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 12855df7e46835c4f103b05407660b4769edd515760fDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 12865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String address = values.getAsString(Email.DATA); 1287ed78fd6df5e9f3a2d572162e5d374d1f4a625bddDmitri Plotnikov 128872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov super.update(db, values, c, callerIsSyncAdapter); 128972e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 129072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov deleteNameLookup(dataId); 129172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 12925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 12935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 12945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 12955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov @Override 12963d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1297b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 1298b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 12993d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 13003d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov int count = super.delete(db, c); 1301568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1302568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov deleteNameLookup(dataId); 1303568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1304568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return count; 1305568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1306bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1307568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1308bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov protected int getTypeRank(int type) { 1309bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov switch (type) { 1310bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov case Email.TYPE_HOME: return 0; 1311568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov case Email.TYPE_WORK: return 1; 1312bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 1313bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 1314bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov default: return 1000; 1315568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1316bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1317bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1318bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1319bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public class NicknameDataRowHandler extends CommonDataRowHandler { 1320bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1321bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public NicknameDataRowHandler() { 1322568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov super(Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL); 1323568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1324bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1325bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov @Override 1326bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1327bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 1328bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1329bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1330bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1331bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1332b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 1333b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return dataId; 1334b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov } 1335bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1336bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov @Override 1337bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1338bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov boolean callerIsSyncAdapter) { 1339bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 1340bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1341bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 1342bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1343bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov super.update(db, values, c, callerIsSyncAdapter); 1344bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1345bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov deleteNameLookup(dataId); 1346bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 1347bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1348bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1349bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1350bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov @Override 1351bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1352bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 1353bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1354bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1355bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov int count = super.delete(db, c); 1356bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1357bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov deleteNameLookup(dataId); 1358bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1359bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return count; 1360bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1361bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov } 1362bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1363bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 13643d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 13653d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov public PhoneDataRowHandler() { 13663d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 1367568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 13680e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 13693d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov @Override 13703d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1371bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov long dataId; 1372bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 1373bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 1374bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1375bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 1376bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 13773d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 13783d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 13793d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 1380bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1381bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 13823d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 13833d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 1384a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov return dataId; 1385a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1386a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1387a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 1388b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 13893826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov boolean callerIsSyncAdapter) { 1390a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 1391a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1392568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 139315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 1394568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number, values); 1395568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1396568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov super.update(db, values, c, callerIsSyncAdapter); 1397568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1398568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 139915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 140015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 140115c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } else { 140215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov super.update(db, values, c, callerIsSyncAdapter); 140315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 140415c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 140515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 140615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov @Override 140715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 140815c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 140915c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1410ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov 1411568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov int count = super.delete(db, c); 1412568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1413568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, null, null); 1414568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 1415568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 141615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov return count; 1417568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 1418568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1419568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private String computeNormalizedNumber(String number, ContentValues values) { 1420568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov String normalizedNumber = null; 1421568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov if (number != null) { 142215c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 1423bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1424bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 1425bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return normalizedNumber; 1426bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 1427bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov 1428bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 1429bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov String number, String normalizedNumber) { 1430bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (number != null) { 1431bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 1432bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 1433bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 1434bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 1435bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.MIN_MATCH, 1436bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov PhoneNumberUtils.toCallerIDMinMatch(number)); 143715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov 1438568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov db.replace(Tables.PHONE_LOOKUP, null, phoneValues); 1439568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } else { 1440568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 1441568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=?", mSelectionArgs1); 1442568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 144315c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov } 1444568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 1445568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 1446568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected int getTypeRank(int type) { 1447568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov switch (type) { 1448568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 1449568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov case Phone.TYPE_WORK: return 1; 145015c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov case Phone.TYPE_HOME: return 2; 1451568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov case Phone.TYPE_PAGER: return 3; 1452568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 1453568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov case Phone.TYPE_OTHER: return 5; 14544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case Phone.TYPE_FAX_WORK: return 6; 14557b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 14567b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov default: return 1000; 14577b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov } 14587b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov } 14597b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov } 14607b330a64cdf77ddb1c3e7259a7f069e99b025b51Dmitri Plotnikov 1461285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov public class GroupMembershipRowHandler extends DataRowHandler { 1462bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 1463b5a4add17815167d20a90645779df34cdf45280dFred Quintana public GroupMembershipRowHandler() { 1464b5a4add17815167d20a90645779df34cdf45280dFred Quintana super(GroupMembership.CONTENT_ITEM_TYPE); 1465285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 14661ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana 1467d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov @Override 1468b5a4add17815167d20a90645779df34cdf45280dFred Quintana public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1469b5a4add17815167d20a90645779df34cdf45280dFred Quintana resolveGroupSourceIdInValues(rawContactId, db, values, true); 1470285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1471285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov updateVisibility(rawContactId); 1472285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov return dataId; 14731129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 1474bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 1475b5a4add17815167d20a90645779df34cdf45280dFred Quintana @Override 1476b5a4add17815167d20a90645779df34cdf45280dFred Quintana public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1477285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov boolean callerIsSyncAdapter) { 1478b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1479bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, false); 14801a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey super.update(db, values, c, callerIsSyncAdapter); 14811a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey updateVisibility(rawContactId); 1482b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov } 14831a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 14843826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov @Override 1485bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1486bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 14873826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov int count = super.delete(db, c); 14883826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov updateVisibility(rawContactId); 14893826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return count; 14903826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 1491b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1492b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void updateVisibility(long rawContactId) { 1493bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 1494bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov if (contactId != 0) { 1495bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov mDbHelper.updateContactVisible(contactId); 1496bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov } 1497bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov } 1498bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov 1499bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov private void resolveGroupSourceIdInValues(long rawContactId, SQLiteDatabase db, 1500bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov ContentValues values, boolean isInsert) { 1501bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1502b5a4add17815167d20a90645779df34cdf45280dFred Quintana boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1503bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (containsGroupSourceId && containsGroupId) { 1504b5a4add17815167d20a90645779df34cdf45280dFred Quintana throw new IllegalArgumentException( 1505b5a4add17815167d20a90645779df34cdf45280dFred Quintana "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 15061129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1507d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov } 15088ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov 1509bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov if (!containsGroupSourceId && !containsGroupId) { 1510285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (isInsert) { 1511b5a4add17815167d20a90645779df34cdf45280dFred Quintana throw new IllegalArgumentException( 1512d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1513d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1514a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } else { 1515a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov return; 1516d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov } 1517a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 1518a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 1519a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov if (containsGroupSourceId) { 1520a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1521d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId, 1522d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mInsertedRawContacts.get(rawContactId)); 1523a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov values.remove(GroupMembership.GROUP_SOURCE_ID); 1524a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId); 1525d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov } 1526a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 1527a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 1528b5a4add17815167d20a90645779df34cdf45280dFred Quintana @Override 1529b5a4add17815167d20a90645779df34cdf45280dFred Quintana public boolean isAggregationRequired() { 1530d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov return false; 1531b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 15329d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana } 15339d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana 15349d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana public class PhotoDataRowHandler extends DataRowHandler { 15359d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana 1536b5a4add17815167d20a90645779df34cdf45280dFred Quintana public PhotoDataRowHandler() { 1537b5a4add17815167d20a90645779df34cdf45280dFred Quintana super(Photo.CONTENT_ITEM_TYPE); 1538d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov } 1539b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1540b5a4add17815167d20a90645779df34cdf45280dFred Quintana @Override 1541a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1542a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1543a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1544a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1545d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov } 1546b5a4add17815167d20a90645779df34cdf45280dFred Quintana return dataId; 1547a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 1548b5a4add17815167d20a90645779df34cdf45280dFred Quintana 1549a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov @Override 1550a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor c, 1551285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov boolean callerIsSyncAdapter) { 1552285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1553285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.update(db, values, c, callerIsSyncAdapter); 1554cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 155581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 155681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 155781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov @Override 155881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 155981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 156081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov int count = super.delete(db, c); 156181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1562cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov return count; 1563568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 156451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 15653826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov @Override 15663826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov public boolean isAggregationRequired() { 15673826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return false; 15683826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 156951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 157051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 1571f262d56495ac4ea30d31bd050efb116bd4bb4235Dmitri Plotnikov /** 15723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * An entry in group id cache. It maps the combination of (account type, account name 15733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * and source id) to group row id. 15746d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov */ 15756d9702cec82fd27a1c3093c64df9dcc22744899aDmitri Plotnikov public class GroupIdCacheEntry { 15763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String accountType; 15773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String accountName; 15783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String sourceId; 15793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov long groupId; 15803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 15814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1582de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 1583bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private ContactsDatabaseHelper mDbHelper; 15841129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 1585b5a4add17815167d20a90645779df34cdf45280dFred Quintana private NameSplitter mNameSplitter; 1586f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private NameLookupBuilder mNameLookupBuilder; 1587f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 1588f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana // We will use this much memory (in bits) to optimize the nickname cluster lookup 1589f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private static final int NICKNAME_BLOOM_FILTER_SIZE = 0x1FFF; // =long[128] 1590a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private BitSet mNicknameBloomFilter; 1591a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 159235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private HashMap<String, SoftReference<String[]>> mNicknameClusterCache = Maps.newHashMap(); 1593a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 159435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private PostalSplitter mPostalSplitter; 1595b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov 159635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana // We don't need a soft cache for groups - the assumption is that there will only 159735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana // be a small number of contact groups. The cache is keyed off source id. The value 1598d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // is a list of groups with this group id. 1599d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 16006bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 16016bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private ContactAggregator mContactAggregator; 16026bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 16035ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1604dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1605f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private ContentValues mValues = new ContentValues(); 1606a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private CharArrayBuffer mCharArrayBuffer = new CharArrayBuffer(128); 1607a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1608a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private volatile CountDownLatch mAccessLatch; 16095ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 16105ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private HashMap<Long, Account> mInsertedRawContacts = Maps.newHashMap(); 1611f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private HashSet<Long> mUpdatedRawContacts = Sets.newHashSet(); 1612f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private HashSet<Long> mDirtyRawContacts = Sets.newHashSet(); 1613a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private HashMap<Long, Object> mUpdatedSyncStates = Maps.newHashMap(); 1614a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1615a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private boolean mVisibleTouched = false; 1616a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1617f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private boolean mSyncToNetwork; 1618f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 1619a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton @Override 1620a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton public boolean onCreate() { 1621a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton super.onCreate(); 1622ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1623f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final Context context = getContext(); 1624f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mDbHelper = (ContactsDatabaseHelper)getDatabaseHelper(); 1625ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey mGlobalSearchSupport = new GlobalSearchSupport(this); 1626ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey mLegacyApiSupport = new LegacyApiSupport(context, mDbHelper, this, mGlobalSearchSupport); 1627ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey mContactAggregator = new ContactAggregator(this, mDbHelper); 1628eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 16295aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 163043880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 1631eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 1632eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey mSetPrimaryStatement = db.compileStatement( 1633eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey "UPDATE " + Tables.DATA + 163482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " SET " + Data.IS_PRIMARY + "=(_id=?)" + 163582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 16361f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey " AND " + Data.RAW_CONTACT_ID + "=?"); 16371f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 16381f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey mSetSuperPrimaryStatement = db.compileStatement( 1639a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton "UPDATE " + Tables.DATA + 164081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" + 1641f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1642a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton " AND " + Data.RAW_CONTACT_ID + " IN (" + 1643a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton "SELECT " + RawContacts._ID + 16447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana " FROM " + Tables.RAW_CONTACTS + 16457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana " WHERE " + RawContacts.CONTACT_ID + " =(" + 16467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "SELECT " + RawContacts.CONTACT_ID + 16477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana " FROM " + Tables.RAW_CONTACTS + 1648de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?))"); 1649a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1650a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton mContactsLastTimeContactedUpdate = db.compileStatement( 1651a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton "UPDATE " + Tables.CONTACTS + 1652e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey " SET " + Contacts.LAST_TIME_CONTACTED + "=? " + 1653e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey "WHERE " + Contacts._ID + "=?"); 1654e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 1655e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey mRawContactDisplayNameUpdate = db.compileStatement( 1656e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey "UPDATE " + Tables.RAW_CONTACTS + 1657e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey " SET " + RawContactsColumns.DISPLAY_NAME + "=?," 1658e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey + RawContactsColumns.DISPLAY_NAME_SOURCE + "=?" + 1659e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey " WHERE " + RawContacts._ID + "=?"); 1660e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 1661e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey mLastStatusUpdate = db.compileStatement( 1662e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey "UPDATE " + Tables.CONTACTS + 1663e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey " SET " + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" + 1664e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey "(SELECT " + DataColumns.CONCRETE_ID + 16657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana " FROM " + Tables.STATUS_UPDATES + 1666e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey " JOIN " + Tables.DATA + 1667f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov " ON (" + StatusUpdatesColumns.DATA_ID + "=" 1668f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov + DataColumns.CONCRETE_ID + ")" + 1669e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey " JOIN " + Tables.RAW_CONTACTS + 1670f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov " ON (" + DataColumns.CONCRETE_RAW_CONTACT_ID + "=" 1671f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov + RawContactsColumns.CONCRETE_ID + ")" + 1672f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=?" + 1673e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey " ORDER BY " + StatusUpdates.STATUS_TIMESTAMP + " DESC," 1674e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey + StatusUpdates.STATUS + 1675e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey " LIMIT 1)" + 1676e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey " WHERE " + ContactsColumns.CONCRETE_ID + "=?"); 1677e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 1678fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov final Locale locale = Locale.getDefault(); 1679fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov mNameSplitter = new NameSplitter( 1680e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey context.getString(com.android.internal.R.string.common_name_prefixes), 1681e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey context.getString(com.android.internal.R.string.common_last_name_prefixes), 1682e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey context.getString(com.android.internal.R.string.common_name_suffixes), 1683e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey context.getString(com.android.internal.R.string.common_name_conjunctions), 1684e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey locale); 1685e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 1686e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey mPostalSplitter = new PostalSplitter(locale); 1687e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 1688e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey mNameLookupInsert = db.compileStatement("INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "(" 1689e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey + NameLookupColumns.RAW_CONTACT_ID + "," + NameLookupColumns.DATA_ID + "," 1690e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey + NameLookupColumns.NAME_TYPE + "," + NameLookupColumns.NORMALIZED_NAME 1691e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey + ") VALUES (?,?,?,?)"); 1692fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov mNameLookupDelete = db.compileStatement("DELETE FROM " + Tables.NAME_LOOKUP + " WHERE " 1693fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov + NameLookupColumns.DATA_ID + "=?"); 1694e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 1695e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey mStatusUpdateInsert = db.compileStatement( 1696e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey "INSERT INTO " + Tables.STATUS_UPDATES + "(" 1697f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 1698f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov + StatusUpdates.STATUS + "," 1699e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey + StatusUpdates.STATUS_RES_PACKAGE + "," 1700f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 1701f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 1702e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey " VALUES (?,?,?,?,?)"); 1703e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 1704f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mStatusUpdateReplace = db.compileStatement( 1705f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "(" 1706e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey + StatusUpdatesColumns.DATA_ID + ", " 1707f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov + StatusUpdates.STATUS_TIMESTAMP + "," 1708f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov + StatusUpdates.STATUS + "," 1709f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 1710f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 1711035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + StatusUpdates.STATUS_LABEL + ")" + 1712f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov " VALUES (?,?,?,?,?,?)"); 1713e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 17147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mStatusUpdateAutoTimestamp = db.compileStatement( 17157e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "UPDATE " + Tables.STATUS_UPDATES + 17167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana " SET " + StatusUpdates.STATUS_TIMESTAMP + "=?," 1717d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + StatusUpdates.STATUS + "=?" + 17186bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?" 17196bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov + " AND " + StatusUpdates.STATUS + "!=?"); 17206bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 17216bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov mStatusAttributionUpdate = db.compileStatement( 1722d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 1723de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov " SET " + StatusUpdates.STATUS_RES_PACKAGE + "=?," 17246bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov + StatusUpdates.STATUS_ICON + "=?," 17256bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov + StatusUpdates.STATUS_LABEL + "=?" + 17266bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1727a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1728a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton mStatusUpdateDelete = db.compileStatement( 1729f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov "DELETE FROM " + Tables.STATUS_UPDATES + 1730f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 1731dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1732a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton mDataRowHandlers = new HashMap<String, DataRowHandler>(); 1733a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1734dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 1735f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 1736f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 1737f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 1738f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 1739e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 17407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 17413d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new NicknameDataRowHandler()); 17423d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 1743f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov new StructuredNameRowHandler(mNameSplitter)); 17443d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 17453d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov new StructuredPostalRowHandler(mPostalSplitter)); 1746f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, new GroupMembershipRowHandler()); 1747f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, new PhotoDataRowHandler()); 1748f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov 1749f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 1750f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov importLegacyContactsAsync(); 1751f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 1752285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 1753285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov verifyAccounts(); 1754d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov 1755f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mMimeTypeIdEmail = mDbHelper.getMimeTypeId(Email.CONTENT_ITEM_TYPE); 1756dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mMimeTypeIdIm = mDbHelper.getMimeTypeId(Im.CONTENT_ITEM_TYPE); 1757dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mMimeTypeIdStructuredName = mDbHelper.getMimeTypeId(StructuredName.CONTENT_ITEM_TYPE); 1758dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mMimeTypeIdOrganization = mDbHelper.getMimeTypeId(Organization.CONTENT_ITEM_TYPE); 1759dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mMimeTypeIdNickname = mDbHelper.getMimeTypeId(Nickname.CONTENT_ITEM_TYPE); 1760dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mMimeTypeIdPhone = mDbHelper.getMimeTypeId(Phone.CONTENT_ITEM_TYPE); 1761dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana preloadNicknameBloomFilter(); 1762dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return (db != null); 1763dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 17643826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 1765023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov protected void verifyAccounts() { 1766a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton AccountManager.get(getContext()).addOnAccountsUpdatedListener(this, null, false); 1767a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton onAccountsUpdated(AccountManager.get(getContext()).getAccounts()); 1768dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1769dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1770dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana /* Visible for testing */ 1771dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana @Override 1772dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 1773dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return ContactsDatabaseHelper.getInstance(context); 1774dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1775dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1776dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana /* package */ NameSplitter getNameSplitter() { 1777dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return mNameSplitter; 1778dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1779dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1780dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana protected boolean isLegacyContactImportNeeded() { 1781dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 1782dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return prefs.getInt(PREF_CONTACTS_IMPORTED, 0) < PREF_CONTACTS_IMPORT_VERSION; 1783dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1784dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1785dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana protected LegacyContactImporter getLegacyContactImporter() { 1786dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return new LegacyContactImporter(getContext(), this); 1787dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1788dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1789dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana /** 1790dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana * Imports legacy contacts in a separate thread. As long as the import process is running 1791dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana * all other access to the contacts is blocked. 1792dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana */ 1793dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void importLegacyContactsAsync() { 1794dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mAccessLatch = new CountDownLatch(1); 1795dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1796dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Thread importThread = new Thread("LegacyContactImport") { 1797dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana @Override 1798dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana public void run() { 1799dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (importLegacyContacts()) { 1800dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // TODO aggregate all newly added raw contacts 1801dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1802dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana /* 1803dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana * When the import process is done, we can unlock the provider and 1804dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana * start aggregating the imported contacts asynchronously. 1805dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana */ 1806dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mAccessLatch.countDown(); 1807dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mAccessLatch = null; 1808dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1809dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1810dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana }; 1811dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1812dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana importThread.start(); 1813dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1814dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1815dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private boolean importLegacyContacts() { 1816dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana LegacyContactImporter importer = getLegacyContactImporter(); 1817dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (importLegacyContacts(importer)) { 1818dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 1819dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Editor editor = prefs.edit(); 1820a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton editor.putInt(PREF_CONTACTS_IMPORTED, PREF_CONTACTS_IMPORT_VERSION); 1821a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton editor.commit(); 1822a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return true; 1823a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } else { 1824a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return false; 1825a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1826f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana } 1827a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1828de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov /* Visible for testing */ 1829de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 183067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey boolean aggregatorEnabled = mContactAggregator.isEnabled(); 1831de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mContactAggregator.setEnabled(false); 183220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 1833de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov importer.importContacts(); 1834de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mContactAggregator.setEnabled(aggregatorEnabled); 1835de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return true; 1836b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov } catch (Throwable e) { 1837de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 1838de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return false; 1839508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 1840de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 1841de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 1842de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov /** 1843de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov * Wipes all data from the contacts database. 1844de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov */ 18454097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov /* package */ void wipeData() { 1846b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.wipeData(); 1847de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 1848a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1849a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov /** 1850d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov * While importing and aggregating contacts, this content provider will 1851f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana * block all attempts to change contacts data. In particular, it will hold 1852d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 1853a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * processes waiting to write to the provider are unblocked and can proceed 1854d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov * to compete for the database transaction monitor. 1855a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 18564f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private void waitForAccess() { 18574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton CountDownLatch latch = mAccessLatch; 1858ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov if (latch != null) { 18598ab0b7a48efe540226253567bcf6fdbc487186a2Dmitri Plotnikov while (true) { 1860d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov try { 1861d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov latch.await(); 18629261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana mAccessLatch = null; 186320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return; 186420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } catch (InterruptedException e) { 1865f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana Thread.currentThread().interrupt(); 186620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 186720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 1868de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 1869de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 1870f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 1871f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov @Override 1872de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 1873de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov waitForAccess(); 1874f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov return super.insert(uri, values); 1875f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 1876a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1877d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov @Override 1878f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 1879d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov waitForAccess(); 188088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 188120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 188220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1883de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 188420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 188520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov waitForAccess(); 188620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 188720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 188820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 188988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov @Override 189088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 189188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov throws OperationApplicationException { 189220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov waitForAccess(); 1893f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov return super.applyBatch(operations); 189488e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 189588e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov 18964da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov @Override 1897f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov protected void onBeginTransaction() { 18984da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (VERBOSE_LOGGING) { 1899f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov Log.v(TAG, "onBeginTransaction"); 190020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 190120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov super.onBeginTransaction(); 190220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mContactAggregator.clearPendingAggregations(); 190320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov clearTransactionalChanges(); 190420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 1905f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov 190620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private void clearTransactionalChanges() { 190720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mInsertedRawContacts.clear(); 190820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mUpdatedRawContacts.clear(); 190920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mUpdatedSyncStates.clear(); 191020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mDirtyRawContacts.clear(); 191120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 191220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 191320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov @Override 191420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov protected void beforeTransactionCommit() { 19157a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana 191620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (VERBOSE_LOGGING) { 191720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov Log.v(TAG, "beforeTransactionCommit"); 191820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 1919a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super.beforeTransactionCommit(); 1920d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov flushTransactionalChanges(); 192120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mContactAggregator.aggregateInTransaction(mDb); 192220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (mVisibleTouched) { 192320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mVisibleTouched = false; 192420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mDbHelper.updateAllVisible(); 192520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 192620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 1927ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1928ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private void flushTransactionalChanges() { 1929f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (VERBOSE_LOGGING) { 1930f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov Log.v(TAG, "flushTransactionChanges"); 1931f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 1932f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 1933e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey for (long rawContactId : mInsertedRawContacts.keySet()) { 1934ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey updateRawContactDisplayName(mDb, rawContactId); 1935ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey mContactAggregator.onRawContactInsert(mDb, rawContactId); 1936f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 193767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 1938f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (!mDirtyRawContacts.isEmpty()) { 193967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mSb.setLength(0); 1940f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 1941ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey appendIds(mSb, mDirtyRawContacts); 1942dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mSb.append(")"); 1943dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDb.execSQL(mSb.toString()); 1944dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1945dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1946f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!mUpdatedRawContacts.isEmpty()) { 1947f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mSb.setLength(0); 194873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 194973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov appendIds(mSb, mUpdatedRawContacts); 1950f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mSb.append(")"); 1951ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey mDb.execSQL(mSb.toString()); 1952dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1953dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1954dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana for (Map.Entry<Long, Object> entry : mUpdatedSyncStates.entrySet()) { 1955dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana long id = entry.getKey(); 1956dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDbHelper.getSyncState().update(mDb, id, entry.getValue()); 1957dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1958dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1959dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana clearTransactionalChanges(); 1960dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1961dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1962dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana /** 1963dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana * Appends comma separated ids. 1964dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana * @param ids Should not be empty 1965dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana */ 1966dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void appendIds(StringBuilder sb, HashSet<Long> ids) { 1967dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana for (long id : ids) { 1968892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.append(id).append(','); 1969892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 1970892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov 1971892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 1972892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 1973d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov 1974892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov @Override 1975dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana protected void notifyChange() { 1976892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov notifyChange(mSyncToNetwork); 1977892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov mSyncToNetwork = false; 1978dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1979dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1980dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana protected void notifyChange(boolean syncToNetwork) { 1981f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 19821a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey syncToNetwork); 1983ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 1984ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 1985ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey private boolean isNewRawContact(long rawContactId) { 1986ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return mInsertedRawContacts.containsKey(rawContactId); 1987ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 19885aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 1989e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey private DataRowHandler getDataRowHandler(final String mimeType) { 19905aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey DataRowHandler handler = mDataRowHandlers.get(mimeType); 19911a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (handler == null) { 19921a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey handler = new CustomDataRowHandler(mimeType); 1993e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey mDataRowHandlers.put(mimeType, handler); 19941a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 1995e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return handler; 1996e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 1997e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 1998ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey @Override 199982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 20001f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (VERBOSE_LOGGING) { 200182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Log.v(TAG, "insertInTransaction: " + uri + " " + values); 200282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 20030a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 20044dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov final boolean callerIsSyncAdapter = 20054dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 20060a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 200782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final int match = sUriMatcher.match(uri); 20084dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov long id = 0; 20094dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 20104dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov switch (match) { 20114dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov case SYNCSTATE: 20121f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey id = mDbHelper.getSyncState().insert(mDb, values); 20131f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 2014dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2015dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton case CONTACTS: { 201682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov insertContact(values); 2017f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov break; 20182526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov } 2019dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2020dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton case RAW_CONTACTS: { 2021dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton id = insertRawContact(uri, values); 20222526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 20232526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov break; 20241f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 2025dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2026dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton case RAW_CONTACTS_DATA: { 20270a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 20280a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov id = insertData(values, callerIsSyncAdapter); 20290a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 20300a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov break; 2031dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 2032dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 2033dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton case DATA: { 20342a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov id = insertData(values, callerIsSyncAdapter); 2035dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton mSyncToNetwork |= !callerIsSyncAdapter; 20362a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov break; 2037f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov } 2038f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 2039f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov case GROUPS: { 2040f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov id = insertGroup(uri, values, callerIsSyncAdapter); 2041f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2042f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov break; 2043f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov } 20442526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 20452526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov case SETTINGS: { 20462526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov id = insertSettings(uri, values); 20472526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 20482526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov break; 20492526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov } 20502526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 20512526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov case STATUS_UPDATES: { 2052dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton id = insertStatusUpdate(values); 20532526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov break; 20542526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov } 2055dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 20562526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov default: 20572526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSyncToNetwork = true; 2058dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton return mLegacyApiSupport.insert(uri, values); 20592526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov } 20602526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 20612526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov if (id < 0) { 20622526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov return null; 20632526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov } 20642526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 2065dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton return ContentUris.withAppendedId(uri, id); 20662526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov } 20672526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 2068dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton /** 2069dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton * If account is non-null then store it in the values. If the account is already 20701f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey * specified in the values then it must be consistent with the account, if it is non-null. 207182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * @param uri the ContentValues to read from and update 20722526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov * @param values the explicitly provided Account 20732526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov * @return false if the parameters are inconsistent 2074dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton */ 207570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov private boolean resolveAccount(Uri uri, ContentValues values) { 2076f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 207770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 20781f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 20791f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) { 2080de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov accountName = null; 20812526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov accountType = null; 20824394086494fe7909aaca70f56fb4bb08beebf303Dmitri Plotnikov } 20831f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 208467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey String valueAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 20855ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov String valueAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2086e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 20871f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (TextUtils.isEmpty(valueAccountName) && TextUtils.isEmpty(valueAccountType)) { 20881f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey values.put(RawContacts.ACCOUNT_NAME, accountName); 20891f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey values.put(RawContacts.ACCOUNT_TYPE, accountType); 20901f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 20911f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (accountName != null && !accountName.equals(valueAccountName)) { 209231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov return false; 209331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 209431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 20951f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (accountType != null && !accountType.equals(valueAccountType)) { 20961f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return false; 209782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 2098a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2099a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov accountName = valueAccountName; 2100a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov accountType = valueAccountType; 2101a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2102a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2103a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) { 2104a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mAccount = null; 210582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov return true; 2106a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 2107a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 210882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (mAccount == null 210982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov || !mAccount.name.equals(accountName) 211082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov || !mAccount.type.equals(accountType)) { 211182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mAccount = new Account(accountName, accountType); 211282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 2113a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 211482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov return true; 211582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 2116aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori 2117aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori /** 21181f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey * Inserts an item in the contacts table 2119a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov * 2120a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov * @param values the values for the new row 2121a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov * @return the row ID of the newly created row 2122e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov */ 21230a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private long insertContact(ContentValues values) { 212482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 212582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 21260a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 21270a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov /** 21280a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov * Inserts an item in the contacts table 21290a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov * 21300a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov * @param uri the values for the new row 21310a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov * @param values the account this contact should be associated with. may be null. 21320a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov * @return the row ID of the newly created row 21330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov */ 21340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private long insertRawContact(Uri uri, ContentValues values) { 21350a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mValues.clear(); 21360a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mValues.putAll(values); 21370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2138a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 213978fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov if (!resolveAccount(uri, mValues)) { 214082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov return -1; 214182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 214278fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov 214378fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 2144a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 214578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 214678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov } 2147e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 2148e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov long rawContactId = mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, mValues); 2149bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId); 2150a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2151f4015ab9ab7c26b766b5331fbf6655b8c54877eaDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 2152a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mInsertedRawContacts.put(rawContactId, mAccount); 2153a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2154a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return rawContactId; 21551f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 21561f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 21574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton /** 2158de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov * Inserts an item in the data table 2159bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov * 2160b5a4add17815167d20a90645779df34cdf45280dFred Quintana * @param values the values for the new row 2161b5a4add17815167d20a90645779df34cdf45280dFred Quintana * @return the row ID of the newly created row 2162b5a4add17815167d20a90645779df34cdf45280dFred Quintana */ 2163f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2164f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana long id = 0; 2165508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey mValues.clear(); 2166508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey mValues.putAll(values); 216735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2168b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 216935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2170b5a4add17815167d20a90645779df34cdf45280dFred Quintana // Replace package with internal mapping 2171b5a4add17815167d20a90645779df34cdf45280dFred Quintana final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2172b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (packageName != null) { 2173b5a4add17815167d20a90645779df34cdf45280dFred Quintana mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 2174b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov } 2175b5a4add17815167d20a90645779df34cdf45280dFred Quintana mValues.remove(Data.RES_PACKAGE); 2176cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2177cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // Replace mimetype with internal mapping 2178cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2179cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2180cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2181d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov } 2182d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 2183dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.getMimeTypeId(mimeType)); 21846bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov mValues.remove(Data.MIMETYPE); 21856bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 21869fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann DataRowHandler rowHandler = getDataRowHandler(mimeType); 21872e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey id = rowHandler.insert(mDb, rawContactId, mValues); 21882e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (!callerIsSyncAdapter) { 21892e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey setRawContactDirty(rawContactId); 2190fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov } 2191fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov mUpdatedRawContacts.add(rawContactId); 21922e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 21932e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (rowHandler.isAggregationRequired()) { 21942e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey triggerAggregation(rawContactId); 2195dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 21962e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey return id; 21972e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 21989fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 21999fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann private void triggerAggregation(long rawContactId) { 22009fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (!mContactAggregator.isEnabled()) { 22019fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return; 22029fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 22039fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 2204a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov int aggregationMode = mDbHelper.getAggregationMode(rawContactId); 22059fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann switch (aggregationMode) { 22069fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case RawContacts.AGGREGATION_MODE_DISABLED: 22079fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann break; 22089fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 22099fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case RawContacts.AGGREGATION_MODE_DEFAULT: { 22109fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann mContactAggregator.markForAggregation(rawContactId); 22119fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann break; 22129fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 221360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann 22149fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case RawContacts.AGGREGATION_MODE_SUSPENDED: { 22159fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann long contactId = mDbHelper.getContactId(rawContactId); 22169fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 22179fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (contactId != 0) { 22189fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann mContactAggregator.updateAggregateData(contactId); 22199fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 2220dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana break; 22219fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 22229fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 22239fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case RawContacts.AGGREGATION_MODE_IMMEDIATE: { 22249fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann long contactId = mDbHelper.getContactId(rawContactId); 22259fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann mContactAggregator.aggregateContact(mDb, rawContactId, contactId); 22269fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann break; 22279fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 22289fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 22299fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 22309fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 22312971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana /** 22322971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana * Returns the group id of the group with sourceId and the same account as rawContactId. 2233fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov * If the group doesn't already exist then it is first created, 2234fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov * @param db SQLiteDatabase to use for this operation 2235e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong * @param rawContactId the contact this group is associated with 22362971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana * @param sourceId the sourceIf of the group to query or create 22372971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana * @return the group id of the existing or created group 22382971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 2239fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov * @throws IllegalStateException if a group needs to be created but the creation failed 2240fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov */ 2241fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId, 22422971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Account account) { 22432971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 22442971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana if (account == null) { 22452971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana mSelectionArgs1[0] = String.valueOf(rawContactId); 22462971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = db.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, 22472971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana RawContacts._ID + "=?", mSelectionArgs1, null, null, null); 22482971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 22495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (c.moveToFirst()) { 22502971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana String accountName = c.getString(RawContactsQuery.ACCOUNT_NAME); 2251fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov String accountType = c.getString(RawContactsQuery.ACCOUNT_TYPE); 2252fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 2253508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey account = new Account(accountName, accountType); 2254508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 225520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2256f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana } finally { 2257944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong c.close(); 2258f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana } 225920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 226020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 226148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov if (account == null) { 226248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov throw new IllegalArgumentException("if the groupmembership only " 226348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + "has a sourceid the the contact must be associated with " 226448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + "an account"); 2265508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 2266f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 22674da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov ArrayList<GroupIdCacheEntry> entries = mGroupIdCache.get(sourceId); 22684da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (entries == null) { 2269ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey entries = new ArrayList<GroupIdCacheEntry>(1); 2270ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey mGroupIdCache.put(sourceId, entries); 2271ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2272f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 22735aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey int count = entries.size(); 22742971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana for (int i = 0; i < count; i++) { 22752971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana GroupIdCacheEntry entry = entries.get(i); 22762971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana if (entry.accountName.equals(account.name) && entry.accountType.equals(account.type)) { 22772971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return entry.groupId; 22782971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 2279e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 22802971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 22812971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana GroupIdCacheEntry entry = new GroupIdCacheEntry(); 22825aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey entry.accountName = account.name; 22832971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana entry.accountType = account.type; 22842971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana entry.sourceId = sourceId; 22852971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana entries.add(0, entry); 22862971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 228781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov // look up the group that contains this sourceId and has the same account name and type 2288f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana // as the contact refered to by rawContactId 228981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Cursor c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 22902971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 2291508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey new String[]{sourceId, account.name, account.type}, null, null, null); 2292508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey try { 2293eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey if (c.moveToFirst()) { 229443880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov entry.groupId = c.getLong(0); 2295e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else { 2296eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey ContentValues groupValues = new ContentValues(); 2297eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey groupValues.put(Groups.ACCOUNT_NAME, account.name); 229882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov groupValues.put(Groups.ACCOUNT_TYPE, account.type); 22990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov groupValues.put(Groups.SOURCE_ID, sourceId); 23001f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 23011f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (groupId < 0) { 230281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov throw new IllegalStateException("unable to create a new group with " 230381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov + "this sourceid: " + groupValues); 23043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 230581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov entry.groupId = groupId; 2306508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 23074f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } finally { 23084f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.close(); 23091c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov } 2310ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2311b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return entry.groupId; 231294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 2313de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 231494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana private interface DisplayNameQuery { 231594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana public static final String RAW_SQL = 231694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana "SELECT " 231794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + DataColumns.MIMETYPE_ID + "," 2318f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana + Data.IS_PRIMARY + "," 2319de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov + Data.DATA1 + "," 232094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + Organization.TITLE + 232194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana " FROM " + Tables.DATA + 232294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana " WHERE " + Data.RAW_CONTACT_ID + "=?" + 2323f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana " AND (" + Data.DATA1 + " NOT NULL OR " + 2324de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov Organization.TITLE + " NOT NULL)"; 232594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 232694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana public static final int MIMETYPE = 0; 23271a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey public static final int IS_PRIMARY = 1; 232894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana public static final int DATA = 2; 232994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana public static final int TITLE = 3; 233094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 23315aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 2332e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey /** 23331a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey * Updates a raw contact display name based on data rows, e.g. structured name, 2334e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey * organization, email etc. 2335e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey */ 2336e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey private void updateRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 2337dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String bestDisplayName = null; 233896b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker int bestDisplayNameSource = DisplayNameSources.UNDEFINED; 2339cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 234096b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = String.valueOf(rawContactId); 234196b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker Cursor c = db.rawQuery(DisplayNameQuery.RAW_SQL, mSelectionArgs1); 2342cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 2343cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 2344cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov int mimeType = c.getInt(DisplayNameQuery.MIMETYPE); 2345dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2346cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // Display name is at DATA1 in all type. This is ensured in the 2347cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // constructor. 2348cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mCharArrayBuffer.sizeCopied = 0; 2349cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.DATA, mCharArrayBuffer); 2350cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov if (mimeType == mMimeTypeIdOrganization && mCharArrayBuffer.sizeCopied == 0) { 23513826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.TITLE, mCharArrayBuffer); 23523826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 2353cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 2354cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 2355cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov int source = getDisplayNameSource(mimeType); 2356fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov if (source > bestDisplayNameSource) { 23573389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov bestDisplayNameSource = source; 23583826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 23593826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 2360f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana } else if (source == bestDisplayNameSource 236114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov && source != DisplayNameSources.UNDEFINED) { 2362fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov if (mimeType == mMimeTypeIdStructuredName 2363fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov || c.getInt(DisplayNameQuery.IS_PRIMARY) != 0) { 2364fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov bestDisplayNameSource = source; 236533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 2366b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mCharArrayBuffer.sizeCopied); 2367dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 236833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 236933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 237033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 23710a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 23729705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } finally { 23739705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori c.close(); 23749705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 23759705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 23769705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori setDisplayName(rawContactId, bestDisplayName, bestDisplayNameSource); 23779705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 23789705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 23799705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int getDisplayNameSource(int mimeTypeId) { 23800a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (mimeTypeId == mMimeTypeIdStructuredName) { 23810a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return DisplayNameSources.STRUCTURED_NAME; 2382dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else if (mimeTypeId == mMimeTypeIdEmail) { 238381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov return DisplayNameSources.EMAIL; 238481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdPhone) { 2385cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return DisplayNameSources.PHONE; 2386cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdOrganization) { 2387cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return DisplayNameSources.ORGANIZATION; 2388cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdNickname) { 2389cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return DisplayNameSources.NICKNAME; 2390cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } else { 2391dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return DisplayNameSources.UNDEFINED; 2392cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 2393cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 23944f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2395de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov /** 2396de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 2397bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov */ 2398b5a4add17815167d20a90645779df34cdf45280dFred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 2399b5a4add17815167d20a90645779df34cdf45280dFred Quintana int count = 0; 2400b5a4add17815167d20a90645779df34cdf45280dFred Quintana 240135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana // Note that the query will return data according to the access restrictions, 240200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar // so we don't need to worry about deleting data we don't have permission to read. 240300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, selection, selectionArgs, null); 2404b5a4add17815167d20a90645779df34cdf45280dFred Quintana try { 2405b5a4add17815167d20a90645779df34cdf45280dFred Quintana while(c.moveToNext()) { 24061129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 2407d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 2408b5a4add17815167d20a90645779df34cdf45280dFred Quintana DataRowHandler rowHandler = getDataRowHandler(mimeType); 2409b5a4add17815167d20a90645779df34cdf45280dFred Quintana count += rowHandler.delete(mDb, c); 2410b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (!callerIsSyncAdapter) { 2411f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana setRawContactDirty(rawContactId); 2412f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (rowHandler.isAggregationRequired()) { 241300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar triggerAggregation(rawContactId); 241435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana } 2415b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov } 2416b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2417b5a4add17815167d20a90645779df34cdf45280dFred Quintana } finally { 2418b5a4add17815167d20a90645779df34cdf45280dFred Quintana c.close(); 2419b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2420b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2421b5a4add17815167d20a90645779df34cdf45280dFred Quintana return count; 2422b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2423b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov 2424b5a4add17815167d20a90645779df34cdf45280dFred Quintana /** 2425b5a4add17815167d20a90645779df34cdf45280dFred Quintana * Delete a data row provided that it is one of the allowed mime types. 242635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana */ 2427d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 2428dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 242900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar // Note that the query will return data according to the access restrictions, 243000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar // so we don't need to worry about deleting data we don't have permission to read. 243100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar mSelectionArgs1[0] = String.valueOf(dataId); 2432d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, Data._ID + "=?", 2433dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mSelectionArgs1, null); 2434c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 2435c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar try { 2436c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar if (!c.moveToFirst()) { 24372e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey return 0; 24382e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 24392e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 24402e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 24412e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey boolean valid = false; 2442fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 2443fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 24442e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey valid = true; 24452e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 24462e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 2447dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 24482e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 24492e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (!valid) { 24502e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey throw new IllegalArgumentException("Data type mismatch: expected " 24517d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + Lists.newArrayList(allowedMimeTypes)); 24527d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 24537d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 24547d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh DataRowHandler rowHandler = getDataRowHandler(mimeType); 24557d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh int count = rowHandler.delete(mDb, c); 24567d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 24577d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh if (rowHandler.isAggregationRequired()) { 24587d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh triggerAggregation(rawContactId); 24597d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 24607d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh return count; 246120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 2462944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong c.close(); 2463f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana } 246481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2465f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 246681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov /** 246720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Inserts an item in the groups table 246820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 2469c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private long insertGroup(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 247048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov mValues.clear(); 247148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov mValues.putAll(values); 247248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 247348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov if (!resolveAccount(uri, mValues)) { 2474f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return -1; 247581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2476f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 247781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov // Replace package with internal mapping 247800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final String packageName = mValues.getAsString(Groups.RES_PACKAGE); 247900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar if (packageName != null) { 24807e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 24815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 24825ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey mValues.remove(Groups.RES_PACKAGE); 2483dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 24847e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (!callerIsSyncAdapter) { 24857e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mValues.put(Groups.DIRTY, 1); 24867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 24875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 248833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long result = mDb.insert(Tables.GROUPS, Groups.TITLE, mValues); 24894529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 24904da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (mValues.containsKey(Groups.GROUP_VISIBLE)) { 24914da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mVisibleTouched = true; 2492dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2493dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 24944529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return result; 24954da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 2496dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2497dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private long insertSettings(Uri uri, ContentValues values) { 24984529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov final long id = mDb.insert(Tables.SETTINGS, null, values); 24997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 25017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mVisibleTouched = true; 2502ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 25035aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 2504f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana return id; 250581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2506f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 250781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov /** 2508ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts a status update. 2509ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 2510ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public long insertStatusUpdate(ContentValues values) { 2511ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 2512ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 25134da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String customProtocol = null; 25144da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov 251573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 25165aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 25175aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey if (TextUtils.isEmpty(customProtocol)) { 251881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov throw new IllegalArgumentException( 2519f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 252081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 2521ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2522ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2523ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long rawContactId = -1; 2524127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov long contactId = -1; 2525de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 2526b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov mSb.setLength(0); 2527b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov if (dataId != null) { 2528b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Lookup the contact info for the given data row. 2529eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 2530e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey mSb.append(Tables.DATA + "." + Data._ID + "="); 2531e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey mSb.append(dataId); 253243880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov } else { 2533eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey // Lookup the data row to attach this presence update to 2534eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 2535eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey if (TextUtils.isEmpty(handle) || protocol == null) { 25369705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 25379705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25389705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 25399705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO: generalize to allow other providers to match against email 25409705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 254172e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 2542bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov if (matchEmail) { 254372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov 2544d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 2545d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 2546d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov // the raw_contacts table. 254781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 254881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 2549f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov // column - Data.DATA1 255081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (") 255100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar .append(mMimeTypeIdEmail) 255200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar .append(",") 255300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar .append(mMimeTypeIdIm) 25544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton .append(")" + " AND " + Data.DATA1 + "="); 25554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton DatabaseUtils.appendEscapedSQLString(mSb, handle); 25569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(" AND ((" + DataColumns.MIMETYPE_ID + "=") 25579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori .append(mMimeTypeIdIm) 25589705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori .append(" AND " + Im.PROTOCOL + "=") 25599705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori .append(protocol); 25609705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (customProtocol != null) { 25619705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 25629705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori DatabaseUtils.appendEscapedSQLString(mSb, customProtocol); 25639705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25649705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=") 25659705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori .append(mMimeTypeIdEmail) 25669705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori .append("))"); 25679705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } else { 25689705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(DataColumns.MIMETYPE_ID + "=") 25699705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori .append(mMimeTypeIdIm) 25709705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori .append(" AND " + Im.PROTOCOL + "=") 25719705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori .append(protocol) 25729705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori .append(" AND " + Im.DATA + "="); 25739705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori DatabaseUtils.appendEscapedSQLString(mSb, handle); 25749705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (customProtocol != null) { 25759705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "="); 25769705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori DatabaseUtils.appendEscapedSQLString(mSb, customProtocol); 25779705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25789705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25799705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 25809705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (values.containsKey(StatusUpdates.DATA_ID)) { 25819705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(" AND " + DataColumns.CONCRETE_ID + "=") 25829705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori .append(values.getAsLong(StatusUpdates.DATA_ID)); 25839705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25849705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 25859705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(" AND ").append(getContactsRestrictions()); 25869705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 25879705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Cursor cursor = null; 25889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori try { 25899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 25909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.toString(), null, null, null, 25919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Contacts.IN_VISIBLE_GROUP + " DESC, " + Data.RAW_CONTACT_ID); 25929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (cursor.moveToFirst()) { 25939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori dataId = cursor.getLong(DataContactsQuery.DATA_ID); 25949705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 25959705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 25969705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } else { 25979705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // No contact found, return a null URI 25989705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return -1; 25999705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 26009705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } finally { 26019705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (cursor != null) { 26029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori cursor.close(); 26039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 26049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 26059705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 26069705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (values.containsKey(StatusUpdates.PRESENCE)) { 26079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (customProtocol == null) { 26089705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // We cannot allow a null in the custom protocol field, because SQLite3 does not 26099705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // properly enforce uniqueness of null values 2610aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori customProtocol = ""; 2611aabcd1d34a71ad06ee0a9395331540484f1ceb17Vasu Nori } 26129705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 26139705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 26149705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.put(StatusUpdates.DATA_ID, dataId); 26155aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 2616f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(PresenceColumns.CONTACT_ID, contactId); 261773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 2618ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 2619ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 262073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 2621f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 262273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 262373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 262473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 262573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 262673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov // Insert the presence update 262773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 262873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 262973776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 2630ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 26311a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(StatusUpdates.STATUS)) { 26321a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey String status = values.getAsString(StatusUpdates.STATUS); 263394021b213e4db367f60b30fcbfe9019e28571784Fred Quintana String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 26346ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Integer labelResource = values.getAsInteger(StatusUpdates.STATUS_LABEL); 26351129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 26366ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (TextUtils.isEmpty(resPackage) 2637e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey && (labelResource == null || labelResource == 0) 26386ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi && protocol != null) { 26396ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi labelResource = Im.getProtocolLabelResource(protocol); 26406ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 26416ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi 26426ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Long iconResource = values.getAsLong(StatusUpdates.STATUS_ICON); 26436ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi // TODO compute the default icon based on the protocol 26446ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi 26456ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (TextUtils.isEmpty(status)) { 26466ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi mStatusUpdateDelete.bindLong(1, dataId); 2647ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mStatusUpdateDelete.execute(); 26486ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } else if (values.containsKey(StatusUpdates.STATUS_TIMESTAMP)) { 26496ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 26506ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi mStatusUpdateReplace.bindLong(1, dataId); 26516ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi mStatusUpdateReplace.bindLong(2, timestamp); 26526ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 3, status); 26536ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 4, resPackage); 26546ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 5, iconResource); 26556ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi DatabaseUtils.bindObjectToProgram(mStatusUpdateReplace, 6, labelResource); 265694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mStatusUpdateReplace.execute(); 265794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 265894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 2659b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov try { 2660b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mStatusUpdateInsert.bindLong(1, dataId); 2661e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 2, status); 26621a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 3, resPackage); 26631a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 4, iconResource); 2664e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey DatabaseUtils.bindObjectToProgram(mStatusUpdateInsert, 5, labelResource); 2665e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey mStatusUpdateInsert.executeInsert(); 2666e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } catch (SQLiteConstraintException e) { 2667e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // The row already exists - update it 2668dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana long timestamp = System.currentTimeMillis(); 2669dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mStatusUpdateAutoTimestamp.bindLong(1, timestamp); 26704529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateAutoTimestamp, 2, status); 26714529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(3, dataId); 26724529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusUpdateAutoTimestamp, 4, status); 26734529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mStatusUpdateAutoTimestamp.execute(); 267473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 267597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 1, resPackage); 267697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 2, iconResource); 267797fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mStatusAttributionUpdate, 3, labelResource); 267897fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov mStatusAttributionUpdate.bindLong(4, dataId); 267997fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov mStatusAttributionUpdate.execute(); 26804529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 2681b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov } 268251bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey } 26834529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 26844529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (contactId != -1) { 26854529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mLastStatusUpdate.bindLong(1, contactId); 26864529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mLastStatusUpdate.bindLong(2, contactId); 2687dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mLastStatusUpdate.execute(); 26884529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 26894529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 26904529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return dataId; 26914529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 26924529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 26934529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov @Override 26944529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 26954529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (VERBOSE_LOGGING) { 26964529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov Log.v(TAG, "deleteInTransaction: " + uri); 2697dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2698dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana flushTransactionalChanges(); 269996b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker final boolean callerIsSyncAdapter = 270096b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 270119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final int match = sUriMatcher.match(uri); 270219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka switch (match) { 270319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka case SYNCSTATE: 2704ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selection, selectionArgs); 2705ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 270619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka case SYNCSTATE_ID: 270719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String selectionWithId = 270896b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 270919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka + (selection == null ? "" : " AND (" + selection + ")"); 271019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka return mDbHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 271119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 2712ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov case CONTACTS: { 2713ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // TODO 271419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka return 0; 271519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 271619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 271719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka case CONTACTS_ID: { 271819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka long contactId = ContentUris.parseId(uri); 271919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka return deleteContact(contactId); 272019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 2721f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 272296b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker case CONTACTS_LOOKUP: 27235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 2724f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov final List<String> pathSegments = uri.getPathSegments(); 2725f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov final int segmentCount = pathSegments.size(); 2726f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (segmentCount < 3) { 2727f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 2728f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 2729f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov final String lookupKey = pathSegments.get(2); 273069cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 2731f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov return deleteContact(contactId); 2732f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 2733433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey 2734dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana case RAW_CONTACTS: { 2735dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana int numDeletes = 0; 2736dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 2737dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 27384529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 2739dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (c.moveToNext()) { 2740dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final long rawContactId = c.getLong(0); 2741dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana numDeletes += deleteRawContact(rawContactId, callerIsSyncAdapter); 2742dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2743dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 2744dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana c.close(); 2745dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2746dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return numDeletes; 2747dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2748dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2749dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana case RAW_CONTACTS_ID: { 2750dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final long rawContactId = ContentUris.parseId(uri); 2751dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteRawContact(rawContactId, callerIsSyncAdapter); 2752dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2753dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2754dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana case DATA: { 2755dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2756433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 2757dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 2758285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 27592b7a632bba423357ae5641f94da6a2f71afc523bDmitri Plotnikov 2760285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov case DATA_ID: 2761f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov case PHONES_ID: 2762f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov case EMAILS_ID: 2763f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov case POSTALS_ID: { 2764f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov long dataId = ContentUris.parseId(uri); 2765f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 276678fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 2767f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov return deleteData(Data._ID + "=?", mSelectionArgs1, callerIsSyncAdapter); 2768f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 2769f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 277019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka case GROUPS_ID: { 2771d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2772d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 277319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 27745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 27755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case GROUPS: { 277633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov int numDeletes = 0; 277733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 2778321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 2779f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana try { 278020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov while (c.moveToNext()) { 278120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 278220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 27835ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } finally { 278420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 278520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 278620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (numDeletes > 0) { 278720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 278820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2789b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return numDeletes; 279020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 279120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 279297fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov case SETTINGS: { 279397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 279497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov return deleteSettings(uri, selection, selectionArgs); 279597fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov } 279697fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov 2797653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov case STATUS_UPDATES: { 279820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 2799653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 2800653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 2801f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov default: { 2802f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov mSyncToNetwork = true; 2803653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 2804653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 2805f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana } 280620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 2807653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 2808653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 280920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mGroupIdCache.clear(); 281020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov final long groupMembershipMimetypeId = mDbHelper 2811653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 281220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 281320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 2814f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana + groupId, null); 2815653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 2816653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 2817321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana if (callerIsSyncAdapter) { 2818653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 2819f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } else { 2820a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mValues.clear(); 2821d364d74ce9cc677c10362b8686d7c33fafe78bebDmitri Plotnikov mValues.put(Groups.DELETED, 1); 2822813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov mValues.put(Groups.DIRTY, 1); 2823813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 2824813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 2825a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } finally { 2826321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana mVisibleTouched = true; 2827321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 28288c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 2829dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 28308c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 2831b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 28328c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mVisibleTouched = true; 28338c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 28348c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 28358c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 28368c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int deleteContact(long contactId) { 2837dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 28388c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov RawContacts.CONTACT_ID + "=" + contactId, null, null, null, null); 28398c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 28408c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (c.moveToNext()) { 28418c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long rawContactId = c.getLong(0); 28428c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov markRawContactAsDeleted(rawContactId); 28438c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 28448c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 28458c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov c.close(); 28468c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 2847dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2848dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 2849d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 28508c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 2851b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov public int deleteRawContact(long rawContactId, boolean callerIsSyncAdapter) { 2852d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 2853b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (callerIsSyncAdapter) { 2854d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 2855b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 2856d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov } else { 2857b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.removeContactIfSingleton(rawContactId); 2858d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov return markRawContactAsDeleted(rawContactId); 2859b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov } 2860d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov } 2861d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 2862d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 28638c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // delete from both tables: presence and status_updates 2864d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // TODO should account type/name be appended to the where clause? 2865d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov if (VERBOSE_LOGGING) { 2866d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov Log.v(TAG, "deleting data from status_updates for " + selection); 28678c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 2868c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey mDb.delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 28698c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs); 2870c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 2871c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 28724da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov 287397fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov private int markRawContactAsDeleted(long rawContactId) { 287497fd30388bd6530f86679510cd7b43b9c518bcefDmitri Plotnikov mSyncToNetwork = true; 28758c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 2876dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.clear(); 2877dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.put(RawContacts.DELETED, 1); 2878dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 2879dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 2880dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.putNull(RawContacts.CONTACT_ID); 2881dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.put(RawContacts.DIRTY, 1); 2882dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return updateRawContact(rawContactId, mValues); 2883dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2884dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2885dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana @Override 2886dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana protected int updateInTransaction(Uri uri, ContentValues values, String selection, 2887dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs) { 2888dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (VERBOSE_LOGGING) { 2889dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Log.v(TAG, "updateInTransaction: " + uri); 2890dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 28918c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 28928c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 28938c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 2894b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final int match = sUriMatcher.match(uri); 28958c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (match == SYNCSTATE_ID && selection == null) { 2896b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long rowId = ContentUris.parseId(uri); 28978c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov Object data = values.get(ContactsContract.SyncState.DATA); 2898b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mUpdatedSyncStates.put(rowId, data); 28998c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return 1; 2900b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov } 29018c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov flushTransactionalChanges(); 2902b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final boolean callerIsSyncAdapter = 29038c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 29048c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov switch(match) { 29059b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori case SYNCSTATE: 29066e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori return mDbHelper.getSyncState().update(mDb, values, 29079b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori appendAccountToSelection(uri, selection), selectionArgs); 29089b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 29099b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori case SYNCSTATE_ID: { 29109b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori selection = appendAccountToSelection(uri, selection); 29119b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori String selectionWithId = 29129b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 2913f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov + (selection == null ? "" : " AND (" + selection + ")"); 2914d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 2915127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov selectionWithId, selectionArgs); 2916127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 29170c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 29180c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov case CONTACTS: { 291980c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov count = updateContactOptions(values, selection, selectionArgs); 2920ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov break; 2921ed089fd34d7b3baf29709eb4f2bc14fa35117660Dmitri Plotnikov } 29220c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 29230c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov case CONTACTS_ID: { 29240c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov count = updateContactOptions(ContentUris.parseId(uri), values); 29250c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov break; 29260c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } 29270c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 2928b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case CONTACTS_LOOKUP: 2929127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 29300c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov final List<String> pathSegments = uri.getPathSegments(); 29314da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov final int segmentCount = pathSegments.size(); 29324da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (segmentCount < 3) { 29330c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 29344da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 29354da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov final String lookupKey = pathSegments.get(2); 29360c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 29376bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov count = updateContactOptions(contactId, values); 29386bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov break; 29390c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } 29400c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 29410c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov case RAW_CONTACTS_DATA: { 29420c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov final String rawContactId = uri.getPathSegments().get(1); 2943127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 2944127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 29453389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov 294669cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 294769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov 294869cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov break; 294969cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov } 2950dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 2951bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov case DATA: { 2952bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov count = updateData(uri, values, appendAccountToSelection(uri, selection), 2953127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov selectionArgs, callerIsSyncAdapter); 2954127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov if (count > 0) { 2955127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2956127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 2957b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 2958b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 295970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 2960bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case DATA_ID: 29613826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov case PHONES_ID: 29623826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov case EMAILS_ID: 2963bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov case POSTALS_ID: { 2964f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 2965e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov if (count > 0) { 2966627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 296749d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov } 296870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong break; 296970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 2970dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2971743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov case RAW_CONTACTS: { 2972743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov selection = appendAccountToSelection(uri, selection); 2973743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov count = updateRawContacts(values, selection, selectionArgs); 2974743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov break; 2975e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 2976743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov 2977743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov case RAW_CONTACTS_ID: { 2978743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 2979743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov if (selection != null) { 2980743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 298148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?" 2982627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + " AND(" + selection + ")", selectionArgs); 2983743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } else { 2984627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 2985627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?", mSelectionArgs1); 2986627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 298770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong break; 298870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 298933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 2990e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov case GROUPS: { 2991e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 2992e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov selectionArgs, callerIsSyncAdapter); 2993e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov if (count > 0) { 2994e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2995e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 2996e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov break; 2997e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 2998e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov 2999e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov case GROUPS_ID: { 3000e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov long groupId = ContentUris.parseId(uri); 3001e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(groupId)); 3002e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov String selectionWithId = Groups._ID + "=? " 3003e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 3004e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov count = updateGroups(uri, values, selectionWithId, selectionArgs, 3005e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov callerIsSyncAdapter); 3006e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov if (count > 0) { 3007e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3008e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 3009e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov break; 3010e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 3011e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov 3012e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 3013e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov count = updateAggregationException(mDb, values); 3014e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov break; 3015e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 3016e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov 3017d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov case SETTINGS: { 3018d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov count = updateSettings(uri, values, selection, selectionArgs); 3019d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3020d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 30214458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 3022e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov 3023e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov case STATUS_UPDATES: { 302433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov count = updateStatusUpdate(uri, values, selection, selectionArgs); 302533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov break; 3026e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 302733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 302833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov default: { 302933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov mSyncToNetwork = true; 303033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 303169cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov } 303269cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov } 303369cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov 303433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov return count; 303533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 303669cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov 303769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 303833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov String[] selectionArgs) { 303933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // update status_updates table, if status is provided 304033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // TODO should account type/name be appended to the where clause? 304133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov int updateCount = 0; 304233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 304333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov if (settableValues.size() > 0) { 304433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov updateCount = mDb.update(Tables.STATUS_UPDATES, 304533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov settableValues, 304633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov getWhereClauseForStatusUpdatesTable(selection), 3047bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov selectionArgs); 304833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 3049e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov 3050bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov // now update the Presence table 305133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov settableValues = getSettableColumnsForPresenceTable(values); 305233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov if (settableValues.size() > 0) { 3053e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov updateCount = mDb.update(Tables.PRESENCE, settableValues, 3054e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov selection, selectionArgs); 3055e3e79030101447da07547647bad225686eb9b8dfDmitri Plotnikov } 305670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 305770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong // potentially get updated in this method. 305870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong return updateCount; 305970d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 306073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 30613826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov /** 30623826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov * Build a where clause to select the rows to be updated in status_updates table. 30633826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov */ 30643826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private String getWhereClauseForStatusUpdatesTable(String selection) { 30653826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mSb.setLength(0); 30663826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 3067afb84050536a4472c13efc0e996d31132d254605Dmitri Plotnikov mSb.append(selection); 306870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mSb.append(")"); 3069619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey return mSb.toString(); 30703826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 30713826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 30723826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 30733826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mValues.clear(); 30743826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 30753826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov StatusUpdates.STATUS); 30763826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 30773826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP); 30783826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 30793826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE); 30803826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 30813826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov StatusUpdates.STATUS_LABEL); 30823826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 30833826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov StatusUpdates.STATUS_ICON); 30843826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov return mValues; 30853826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov } 30863826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov 30873826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 30883826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov mValues.clear(); 30893826a44d8de41e9c148dd6a967392ea5af478085Dmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 309072e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov StatusUpdates.PRESENCE); 3091bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return mValues; 3092d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3093d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3094619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 3095627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String[] selectionArgs, boolean callerIsSyncAdapter) { 3096627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3097dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mGroupIdCache.clear(); 3098743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov 3099743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov ContentValues updatedValues; 3100743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 3101627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov updatedValues = mValues; 3102627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov updatedValues.clear(); 3103dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updatedValues.putAll(values); 3104627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 3105627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } else { 3106627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov updatedValues = values; 3107627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 3108627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 3109627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 3110627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 3111627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mVisibleTouched = true; 31124f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 31134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (updatedValues.containsKey(Groups.SHOULD_SYNC) 31144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 311515c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov final long groupId = ContentUris.parseId(uri); 311615c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(groupId); 311715c6e903b6d66e20e7cb1ebe7ff8c713e0a3386bDmitri Plotnikov Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 3118d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Groups.ACCOUNT_TYPE}, Groups._ID + "=?", mSelectionArgs1, null, 3119385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov null, null); 31203716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String accountName; 31213716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String accountType; 3122385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov try { 31233716f1447ceb21180d1301790eabd8b9453f486dDave Santoro while (c.moveToNext()) { 31243716f1447ceb21180d1301790eabd8b9453f486dDave Santoro accountName = c.getString(0); 31253716f1447ceb21180d1301790eabd8b9453f486dDave Santoro accountType = c.getString(1); 3126d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if(!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 31273716f1447ceb21180d1301790eabd8b9453f486dDave Santoro Account account = new Account(accountName, accountType); 31283716f1447ceb21180d1301790eabd8b9453f486dDave Santoro ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 31293716f1447ceb21180d1301790eabd8b9453f486dDave Santoro new Bundle()); 3130d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 3131d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3132d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3133d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } finally { 3134a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov c.close(); 3135a85745ab25f9ab8fd6fd29e174bf2fac5492e448Dmitri Plotnikov } 3136d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3137d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return count; 3138d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3139d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3140d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 3141d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String[] selectionArgs) { 3142d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 3143d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 3144d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov mVisibleTouched = true; 3145d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3146d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return count; 3147d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 31482e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov 31492e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs) { 31502e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 31512e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 31522e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 31532e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov } 3154d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 315509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov int count = 0; 315609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 315709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov new String[] { RawContacts._ID }, selection, 315809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov selectionArgs, null, null, null); 315909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov try { 3160332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov while (cursor.moveToNext()) { 3161d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov long rawContactId = cursor.getLong(0); 31626ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov updateRawContact(rawContactId, values); 31636ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov count++; 31646ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 31656ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } finally { 31666ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov cursor.close(); 3167547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } 3168547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro 3169547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro return count; 3170547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } 3171547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro 3172547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro private int updateRawContact(long rawContactId, ContentValues values) { 31733716f1447ceb21180d1301790eabd8b9453f486dDave Santoro final String selection = RawContacts._ID + " = " + rawContactId; 31743716f1447ceb21180d1301790eabd8b9453f486dDave Santoro final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 3175547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro && values.getAsInteger(RawContacts.DELETED) == 0); 3176547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro int previousDeleted = 0; 3177547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro String accountType = null; 3178547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro String accountName = null; 3179547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro if (requestUndoDelete) { 3180547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro Cursor cursor = mDb.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, selection, 3181547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro null, null, null, null); 31823716f1447ceb21180d1301790eabd8b9453f486dDave Santoro try { 31833716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (cursor.moveToFirst()) { 31843716f1447ceb21180d1301790eabd8b9453f486dDave Santoro previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 31853716f1447ceb21180d1301790eabd8b9453f486dDave Santoro accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 31863716f1447ceb21180d1301790eabd8b9453f486dDave Santoro accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 31873716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 31883716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } finally { 31893716f1447ceb21180d1301790eabd8b9453f486dDave Santoro cursor.close(); 31903716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 31913716f1447ceb21180d1301790eabd8b9453f486dDave Santoro values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 31923716f1447ceb21180d1301790eabd8b9453f486dDave Santoro ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 31933716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 31943716f1447ceb21180d1301790eabd8b9453f486dDave Santoro int count = mDb.update(Tables.RAW_CONTACTS, values, selection, null); 31953716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (count != 0) { 31963716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (values.containsKey(RawContacts.STARRED)) { 31973716f1447ceb21180d1301790eabd8b9453f486dDave Santoro mContactAggregator.updateStarred(rawContactId); 31983716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } 31993716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (values.containsKey(RawContacts.SOURCE_ID)) { 3200547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro mContactAggregator.updateLookupKey(mDb, rawContactId); 3201547c5eddcc79f680dc128b3851bf6cc03b0d0ebfDave Santoro } 32026ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (requestUndoDelete && previousDeleted == 1) { 32036ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov // undo delete, needs aggregation again. 32046ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov mInsertedRawContacts.put(rawContactId, new Account(accountName, accountType)); 32056ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 32066ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 32076ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov return count; 32086ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 32096ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 32106ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov private int updateData(Uri uri, ContentValues values, String selection, 32116ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov String[] selectionArgs, boolean callerIsSyncAdapter) { 32126ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov mValues.clear(); 32136ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov mValues.putAll(values); 32146ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov mValues.remove(Data._ID); 32156ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 32166ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov mValues.remove(Data.MIMETYPE); 32176ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 32186ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 32196ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov if (packageName != null) { 32206ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 32216ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 32226ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov } 32236ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 32246ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 3225332321f2832d52f50b9f8fc1f4006459000a4b21Dmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 32266ca827312e6c69bdd88b48e485debee9fe5d16baDmitri Plotnikov 3227d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 3228d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov // content provider. 3229d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 3230d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov containsIsSuperPrimary = false; 3231d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 3232d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3233d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 3234d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov containsIsPrimary = false; 3235d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 3236d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3237d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3238d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov int count = 0; 3239d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3240d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 3241d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 3242d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Cursor c = query(uri, DataUpdateQuery.COLUMNS, selection, selectionArgs, null); 3243d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov try { 3244d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov while(c.moveToNext()) { 3245d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov count += updateData(mValues, c, callerIsSyncAdapter); 3246d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 32474458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } finally { 32484458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov c.close(); 32494458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 325049d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov 325149d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov return count; 32524458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 32534458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov 32544458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 32554458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov if (values.size() == 0) { 32564458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov return 0; 32574458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov } 32584458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov 32594458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov final String mimeType = c.getString(DataUpdateQuery.MIMETYPE); 32604458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 32614458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov rowHandler.update(mDb, values, c, callerIsSyncAdapter); 32624458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 32634458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov if (rowHandler.isAggregationRequired()) { 32644458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov triggerAggregation(rawContactId); 3265d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 32664458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov 3267d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov return 1; 3268d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 32694458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov 32704458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 3271d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov String[] selectionArgs) { 3272d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov int count = 0; 327372e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getContactView(), 32744458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov new String[] { Contacts._ID }, selection, 32754458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov selectionArgs, null, null, null); 32764458d63ef3384832fd2ad82130d4ad042cce2de6Dmitri Plotnikov try { 327772e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov while (cursor.moveToNext()) { 327872e3003a810fb4793a1513d17a40f8ab83d7d0afDmitri Plotnikov long contactId = cursor.getLong(0); 3279d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov updateContactOptions(contactId, values); 3280385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov count++; 3281bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 3282bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } finally { 3283bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov cursor.close(); 32840b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 3285b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov 328635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana return count; 3287d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 32881f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3289c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private int updateContactOptions(long contactId, ContentValues values) { 3290c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3291619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mValues.clear(); 3292619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 3293a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton values, Contacts.CUSTOM_RINGTONE); 32944f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 329535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana values, Contacts.SEND_TO_VOICEMAIL); 3296b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 329735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana values, Contacts.LAST_TIME_CONTACTED); 329835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 3299d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 3300763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 3301385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov values, Contacts.STARRED); 3302619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 3303619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Nothing to update - just return 3304619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (mValues.size() == 0) { 3305d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov return 0; 33064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 3307763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 33084da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 33094da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov // Mark dirty when changing starred to trigger sync 33106bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 33116bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 33126bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 33135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 33145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?", mSelectionArgs1); 33155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 33165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 33175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // being explicitly updated by clients. 3318fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov mValues.clear(); 3319fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 33205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 3321a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 33225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 33235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 33245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 33255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 3326763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar values, Contacts.TIMES_CONTACTED); 3327a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 3328a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov values, Contacts.STARRED); 3329a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3330a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=?", mSelectionArgs1); 3331a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 33325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 33335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov public void updateContactLastContactedTime(long contactId, long lastTimeContacted) { 33345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov mContactsLastTimeContactedUpdate.bindLong(1, lastTimeContacted); 33355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov mContactsLastTimeContactedUpdate.bindLong(2, contactId); 3336763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar mContactsLastTimeContactedUpdate.execute(); 33374da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 33384da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov 33394da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 33405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 33415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 33425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 33432149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 33442149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov long rawContactId1, rawContactId2; 33452149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (rcId1 < rcId2) { 33462149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov rawContactId1 = rcId1; 33472149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov rawContactId2 = rcId2; 33482149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } else { 33492149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov rawContactId2 = rcId1; 33502149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov rawContactId1 = rcId2; 33512149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 33522149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 33532149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 33542149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov mSelectionArgs2[0] = String.valueOf(rawContactId1); 33552149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov mSelectionArgs2[1] = String.valueOf(rawContactId2); 3356a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 3357a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=? AND " 3358a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=?", mSelectionArgs2); 3359a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } else { 3360a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 33612149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 33622149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 33632149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 33642149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 33652149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov exceptionValues); 33662149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov } 33672149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 33682149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 33692149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1); 33702149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2); 33712149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov 33722149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov long contactId1 = mDbHelper.getContactId(rawContactId1); 33732149ab82f021c204618d0d3644e261fd7a8d8490Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1, contactId1); 3374f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 3375f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey long contactId2 = mDbHelper.getContactId(rawContactId2); 337642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann mContactAggregator.aggregateContact(db, rawContactId2, contactId2); 3377763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 3378f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // The return value is fake - we just confirm that we made a change, not count actual 33794da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov // rows changed. 33804da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return 1; 33814da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 3382f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 3383f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey public void onAccountsUpdated(Account[] accounts) { 3384f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey mDb = mDbHelper.getWritableDatabase(); 338542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann if (mDb == null) return; 338642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 338742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann HashSet<Account> existingAccounts = new HashSet<Account>(); 338842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann boolean hasUnassignedContacts[] = new boolean[]{false}; 338942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann mDb.beginTransaction(); 339042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann try { 339142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann findValidAccounts(existingAccounts, hasUnassignedContacts, 339242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann Tables.RAW_CONTACTS, RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE); 339342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann findValidAccounts(existingAccounts, hasUnassignedContacts, 339442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann Tables.GROUPS, Groups.ACCOUNT_NAME, Groups.ACCOUNT_TYPE); 3395ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov findValidAccounts(existingAccounts, hasUnassignedContacts, 3396916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov Tables.SETTINGS, Settings.ACCOUNT_NAME, Settings.ACCOUNT_TYPE); 3397ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 3398916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov // Remove all valid accounts from the existing account set. What is left 3399ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar // in the existingAccounts set will be extra accounts whose data must be deleted. 34007ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov HashSet<Account> accountsToDelete = new HashSet<Account>(existingAccounts); 34017ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov for (Account account : accounts) { 3402ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar accountsToDelete.remove(account); 3403ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3404ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 3405ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov for (Account account : accountsToDelete) { 3406ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov Log.d(TAG, "removing data for removed account " + account); 34074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String[] params = new String[] {account.name, account.type}; 3408ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov mDb.execSQL( 3409d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar "DELETE FROM " + Tables.GROUPS + 34104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 34114a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " = ?", params); 3412e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov mDb.execSQL( 34135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 34144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 34154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov "SELECT " + RawContacts._ID + 34164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 3417763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 3418ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?)", params); 34195e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar mDb.execSQL( 34205e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar "DELETE FROM " + Tables.RAW_CONTACTS + 34215e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 3422dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?", params); 3423dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov mDb.execSQL( 3424dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 3425dd300fe5f5a1071b1c135af7c76e3ae149edda4dDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 34265e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar " AND " + Settings.ACCOUNT_TYPE + " = ?", params); 34275e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 34284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 34294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (hasUnassignedContacts[0]) { 34304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 3431d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar Account primaryAccount = null; 34325e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar for (Account account : accounts) { 34335e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (isWritableAccount(account)) { 34344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov primaryAccount = account; 3435d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar break; 3436d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3437d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3438763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 34394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (primaryAccount != null) { 34404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String[] params = new String[] {primaryAccount.name, primaryAccount.type}; 3441d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 34425e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar mDb.execSQL( 34435e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar "UPDATE " + Tables.RAW_CONTACTS + 3444d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov " SET " + RawContacts.ACCOUNT_NAME + "=?," 3445d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=?" + 34464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " IS NULL" + 3447d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar " AND " + RawContacts.ACCOUNT_TYPE + " IS NULL", params); 3448d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 3449d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // We don't currently support groups for unsynced accounts, so this is for 3450d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // the future 34514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov mDb.execSQL( 34524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov "UPDATE " + Tables.GROUPS + 3453d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar " SET " + Groups.ACCOUNT_NAME + "=?," 3454d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar + Groups.ACCOUNT_TYPE + "=?" + 3455d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar " WHERE " + Groups.ACCOUNT_NAME + " IS NULL" + 3456d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar " AND " + Groups.ACCOUNT_TYPE + " IS NULL", params); 3457d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3458d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 3459ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 3460763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar mDbHelper.getSyncState().onAccountsChanged(mDb, accounts); 3461b67163a1088f09c59f324350662eb18772fac6b6Evan Millar mDb.setTransactionSuccessful(); 346271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov } finally { 34634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov mDb.endTransaction(); 3464b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3465b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3466b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 3467b67163a1088f09c59f324350662eb18772fac6b6Evan Millar /** 3468a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * Finds all distinct accounts present in the specified table. 34694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 347082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void findValidAccounts(Set<Account> validAccounts, boolean[] hasUnassignedContacts, 34714da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String table, String accountNameColumn, String accountTypeColumn) { 34724da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = mDb.rawQuery("SELECT DISTINCT " + accountNameColumn + "," + accountTypeColumn 34736bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov + " FROM " + table, null); 34746bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov try { 347500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar while (c.moveToNext()) { 3476a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c.isNull(0) && c.isNull(1)) { 34773653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov hasUnassignedContacts[0] = true; 347882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } else { 34794da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov validAccounts.add(new Account(c.getString(0), c.getString(1))); 34804da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 34813653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 34823653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } finally { 34833653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov c.close(); 34843653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 3485a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3486a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3487a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** 3488a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * Test all against {@link TextUtils#isEmpty(CharSequence)}. 3489a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov */ 3490a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static boolean areAllEmpty(ContentValues values, String[] keys) { 3491a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov for (String key : keys) { 3492a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (!TextUtils.isEmpty(values.getAsString(key))) { 3493a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return false; 3494a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3495a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3496a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return true; 3497a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3498a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3499a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov /** 3500a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov * Returns true if a value (possibly null) is specified for at least one of the supplied keys. 3501a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov */ 3502a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static boolean areAnySpecified(ContentValues values, String[] keys) { 3503a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov for (String key : keys) { 3504a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (values.containsKey(key)) { 3505a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return true; 3506a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3507a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3508a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return false; 3509a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3510a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3511a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov @Override 3512a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 3513a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String sortOrder) { 3514a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (VERBOSE_LOGGING) { 3515a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Log.v(TAG, "query: " + uri); 3516a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3517a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3518a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 3519a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3520a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 3521a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String groupBy = null; 3522a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String limit = getLimit(uri); 3523a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 35244a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // TODO: Consider writing a test case for RestrictionExceptions when you 352582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov // write a new query() block to make sure it protects restricted data. 352689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov final int match = sUriMatcher.match(uri); 35272815f58f72f109790585931f601a63ddc02536a5Evan Millar switch (match) { 35282815f58f72f109790585931f601a63ddc02536a5Evan Millar case SYNCSTATE: 35292815f58f72f109790585931f601a63ddc02536a5Evan Millar return mDbHelper.getSyncState().query(db, projection, selection, selectionArgs, 353048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov sortOrder); 353182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 35324da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov case CONTACTS: { 353348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov setTablesAndProjectionMapForContacts(qb, uri, projection); 35344da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov break; 353548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 353648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 353748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case CONTACTS_ID: { 3538ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar long contactId = ContentUris.parseId(uri); 353982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, uri, projection); 354089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 3541ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.appendWhere(Contacts._ID + "=?"); 35424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 35434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 3544a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 35455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case CONTACTS_LOOKUP: 354645d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov case CONTACTS_LOOKUP_ID: { 35475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 35485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov int segmentCount = pathSegments.size(); 35495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (segmentCount < 3) { 3550155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov throw new IllegalArgumentException("URI " + uri + " is missing a lookup key"); 3551155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov } 3552155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov String lookupKey = pathSegments.get(2); 3553155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov if (segmentCount == 4) { 3554155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 3555155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 3556155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 35572352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov String[] args; 3558155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov if (selectionArgs == null) { 35595e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov args = new String[2]; 356045d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov } else { 35615e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov args = new String[selectionArgs.length + 2]; 35625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 3563892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 3564892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov args[0] = String.valueOf(contactId); 35655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov args[1] = lookupKey; 35665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 35675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, args, sortOrder, 35685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy, limit); 3569892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov if (c.getCount() != 0) { 3570892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov return c; 3571892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 3572892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov 3573892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov c.close(); 357445d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov } 357545d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov 357645d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov setTablesAndProjectionMapForContacts(qb, uri, projection); 357745d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 357845d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 357945d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 358045d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov break; 35815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 35825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 3583a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov case CONTACTS_AS_VCARD: { 3584ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar // When reading as vCard always use restricted view 35855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov final String lookupKey = uri.getPathSegments().get(2); 3586a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov qb.setTables(mDbHelper.getContactView(true /* require restricted */)); 3587a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov qb.setProjectionMap(sContactsVCardProjectionMap); 3588a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 3589ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 3590ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.appendWhere(Contacts._ID + "=?"); 3591ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 35924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 359382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 359489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov case CONTACTS_FILTER: { 35954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov setTablesAndProjectionMapForContacts(qb, uri, projection); 35964a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 35974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 359848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 359982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(Contacts._ID + " IN "); 36004da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 36014da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(sb.toString()); 36024da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 360348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 360448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 360548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 36065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 360782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case CONTACTS_STREQUENT: { 360889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov String filterSql = null; 36094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 361008768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov && uri.getPathSegments().size() > 3) { 361108768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 361208768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 361308768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 36144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 3615ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filterSql = sb.toString(); 3616ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3617ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 36185e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov setTablesAndProjectionMapForContacts(qb, uri, projection); 361982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 362007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov String[] starredProjection = null; 36217d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa String[] frequentProjection = null; 36227d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa if (projection != null) { 36237d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa starredProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 36247d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa frequentProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 36257d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa } 36267d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa 362707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // Build the first query for starred 362807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterSql != null) { 362907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(filterSql); 363007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 363107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.setProjectionMap(sStrequentStarredProjectionMap); 363207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov final String starredQuery = qb.buildQuery(starredProjection, Contacts.STARRED + "=1", 36335e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov null, Contacts._ID, null, null, null); 363407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov 363507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // Build the second query for frequent 363607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb = new SQLiteQueryBuilder(); 363707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov setTablesAndProjectionMapForContacts(qb, uri, projection); 363807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterSql != null) { 363907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(filterSql); 364007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 364107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.setProjectionMap(sStrequentFrequentProjectionMap); 364207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov final String frequentQuery = qb.buildQuery(frequentProjection, 36432a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 36442a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 36452a8fefb86282c06a7669f80e1b2b86d87619dfc2Dmitri Plotnikov null, Contacts._ID, null, null, null); 364607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov 364720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov // Put them together 3648155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 3649155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov STREQUENT_ORDER_BY, STREQUENT_LIMIT); 3650155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 3651155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov if (c != null) { 3652155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov c.setNotificationUri(getContext().getContentResolver(), 3653155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov ContactsContract.AUTHORITY_URI); 3654155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov } 3655155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov return c; 3656155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov } 3657155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov 3658155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov case CONTACTS_GROUP: { 3659155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov setTablesAndProjectionMapForContacts(qb, uri, projection); 36602352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 3661155accbcb95fc13b984cf0ea8e5498a9c619cbf5Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 36625e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 36635e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 3664a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov break; 36655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 36665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 3667a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov case CONTACTS_DATA: { 36687d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa long contactId = Long.parseLong(uri.getPathSegments().get(1)); 36697d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, false); 36707d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 36717d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 36727d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa break; 36737d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa } 36747d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa 36757d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa case CONTACTS_PHOTO: { 36767d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa long contactId = Long.parseLong(uri.getPathSegments().get(1)); 36777d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa setTablesAndProjectionMapForData(qb, uri, projection, false); 36787d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 36797d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 36807d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 36817d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa break; 36827d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa } 36837d82ae92714f2132e3a0971d844ae8cdf10d76e7Daisuke Miyakawa 3684a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov case PHONES: { 36855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 36865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 36875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 3688ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 368982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 369089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov case PHONES_ID: { 369189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 3692ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 3693ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 3694ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.appendWhere(" AND " + Data._ID + "=?"); 369548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 369682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 36974da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov 369848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_FILTER: { 369948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 37004da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 370148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 370248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 370348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 37045ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov sb.append(" AND ("); 3705763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 37064f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton boolean orNeeded = false; 37074f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String normalizedName = NameNormalizer.normalize(filterParam); 37084f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (normalizedName.length() > 0) { 37095ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 37105ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, null, false); 3711763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar orNeeded = true; 37124da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 37134da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov 37144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (isPhoneNumber(filterParam)) { 37154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (orNeeded) { 37164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton sb.append(" OR "); 37175ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 37185ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov String number = PhoneNumberUtils.convertKeypadLettersToDigits(filterParam); 371982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String reversed = PhoneNumberUtils.getStrippedReversed(number); 37204da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov sb.append(Data._ID + 37214da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov " IN (SELECT " + PhoneLookupColumns.DATA_ID 3722e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey + " FROM " + Tables.PHONE_LOOKUP 3723e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '%"); 3724e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey sb.append(reversed); 3725e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey sb.append("')"); 372682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 3727e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey sb.append(")"); 3728e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey qb.appendWhere(sb); 3729e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 37304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 373182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (sortOrder == null) { 37324da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 37334da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 3734a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 3735a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 3736a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 3737a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case EMAILS: { 37384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 3739a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 3740a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 3741a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3742892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov 3743a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case EMAILS_ID: { 3744a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton setTablesAndProjectionMapForData(qb, uri, projection, false); 3745e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 3746e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'" 3747e8b3427e88d28a00cdcad7d296544f2459dfc629Dmitri Plotnikov + " AND " + Data._ID + "=?"); 3748892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov break; 3749892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov } 3750892a3d9ded5c64a63ae3d5d5c52c59528b466c93Dmitri Plotnikov 3751e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov case EMAILS_LOOKUP: { 3752e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 3753e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 3754e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov if (uri.getPathSegments().size() > 2) { 3755a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 3756a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton qb.appendWhere(" AND " + Email.DATA + "=?"); 3757a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 3758ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3759b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov } 3760ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 376189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov case EMAILS_FILTER: { 3762ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey setTablesAndProjectionMapForData(qb, uri, projection, true); 3763ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 3764ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (uri.getPathSegments().size() > 2) { 3765ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey String filterParam = uri.getLastPathSegment(); 3766b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 3767ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sb.append(" AND ("); 37684da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov 37694da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (!filterParam.contains("@")) { 3770ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey String normalizedName = NameNormalizer.normalize(filterParam); 3771ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (normalizedName.length() > 0) { 3772ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sb.append(Data.RAW_CONTACT_ID + " IN "); 3773ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey appendRawContactsByNormalizedNameFilter(sb, normalizedName, null, false); 3774b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov sb.append(" OR "); 3775ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 377689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov } 377789c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov 3778ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sb.append(Email.DATA + " LIKE "); 3779ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sb.append(DatabaseUtils.sqlEscapeString(filterParam + '%')); 3780ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sb.append(")"); 3781b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.appendWhere(sb); 37820c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } 3783b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 3784b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov if (sortOrder == null) { 3785b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 3786b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 378731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov break; 3788d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov } 37892d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov 37902d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov case POSTALS: { 37912d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 37922d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 379331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 3794d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov break; 3795d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov } 379631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 379731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case POSTALS_ID: { 379831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 379931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 38005b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 38015b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 38025b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 38035b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov break; 38045b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 38055b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 38065b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov case RAW_CONTACTS: { 38075b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov setTablesAndProjectionMapForRawContacts(qb, uri); 380876dfa406e2cde19c824983c37fc92c1c5bf63eecDaniel Lehmann break; 38095b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov } 38105b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov 38115b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov case RAW_CONTACTS_ID: { 38125b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 38135b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov setTablesAndProjectionMapForRawContacts(qb, uri); 38145b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 38155b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 3816763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar break; 38177581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov } 38187581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 38195b3634b24d3c21618f96860e969fd5c9ba7d9ca8Dmitri Plotnikov case RAW_CONTACTS_DATA: { 382031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 382131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 3822eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 3823eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 3824eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 382589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov } 3826e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3827e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey case DATA: { 3828e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey setTablesAndProjectionMapForData(qb, uri, projection, false); 3829b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov break; 3830e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 383182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 3832b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov case DATA_ID: { 3833e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey setTablesAndProjectionMapForData(qb, uri, projection, false); 3834e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 383582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 3836b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov break; 3837e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3838e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3839e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey case PHONE_LOOKUP: { 3840eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 3841eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey if (TextUtils.isEmpty(sortOrder)) { 3842eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey // Default the sort order to something reasonable so we get consistent 384382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov // results when callers don't request an ordering 38440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sortOrder = RawContactsColumns.CONCRETE_ID; 38455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 38465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 38475ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 384882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mDbHelper.buildPhoneLookupAndContactQuery(qb, number); 38490a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 38504da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov 38514da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov // Phone lookup cannot be combined with a selection 38525ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov selection = null; 38535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov selectionArgs = null; 38545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 3855c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3856174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 3857174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov case GROUPS: { 3858c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 3859c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov qb.setProjectionMap(sGroupsProjectionMap); 3860c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov appendAccountFromParameter(qb, uri); 38612d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill break; 3862174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 3863174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 3864174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov case GROUPS_ID: { 3865174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 3866c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov qb.setProjectionMap(sGroupsProjectionMap); 3867c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 38681b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Groups._ID + "=?"); 3869b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov break; 38701b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov } 38711b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 38721b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case GROUPS_SUMMARY: { 38731b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(mDbHelper.getGroupView() + " AS groups"); 3874b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setProjectionMap(sGroupsSummaryProjectionMap); 38751b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov appendAccountFromParameter(qb, uri); 38761b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov groupBy = Groups._ID; 38771b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 38781b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov } 38791b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 3880b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 38811b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 38821b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 38831b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 38841b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov } 38851b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 3886b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 38871b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 388871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov String filter = null; 38891b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 38901b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov filter = uri.getPathSegments().get(3); 38911b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov } 389246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana final int maxSuggestions; 3893a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (limit != null) { 389446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana maxSuggestions = Integer.parseInt(limit); 389546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } else { 389646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 389746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 389846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 3899a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForContacts(qb, uri, projection); 39004da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov 39014da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 390246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana maxSuggestions, filter); 390346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 390446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 390509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov case SETTINGS: { 390609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov qb.setTables(Tables.SETTINGS); 390709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov qb.setProjectionMap(sSettingsProjectionMap); 390809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov appendAccountFromParameter(qb, uri); 3909d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3910d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov // When requesting specific columns, this query requires 3911d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov // late-binding of the GroupMembership MIME-type. 3912d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov final String groupMembershipMimetypeId = Long.toString(mDbHelper 3913d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 3914d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (projection != null && projection.length != 0 && 3915d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 3916385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3917d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3918d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (projection != null && projection.length != 0 && 3919385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 3920d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 3921d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 3922d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 3923d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov break; 39247a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 39257a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 39267a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov case STATUS_UPDATES: { 39277a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 39284f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 3929f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 3930c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 39314f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case STATUS_UPDATES_ID: { 39324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton setTableAndProjectionMapForStatusUpdates(qb, projection); 39337f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 39347f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=?"); 3935ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov break; 3936ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 3937ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 3938ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov case SEARCH_SUGGESTIONS: { 3939ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 3940ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 39415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case SEARCH_SHORTCUT: { 39435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = ContentUris.parseId(uri); 39445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return mGlobalSearchSupport.handleSearchShortcutRefresh(db, contactId, projection); 39455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 3946038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana 3947038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana case LIVE_FOLDERS_CONTACTS: 3948038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setTables(mDbHelper.getContactView()); 3949038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sLiveFoldersProjectionMap); 39505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 39515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 39524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 39534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton qb.setTables(mDbHelper.getContactView()); 39544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton qb.setProjectionMap(sLiveFoldersProjectionMap); 39554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 39564f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 39574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 395809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 395909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 396009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 396109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 396209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov break; 396309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 396409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 396509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 396609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 396709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 396809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 396909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov break; 397009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 397109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov case RAW_CONTACT_ENTITIES: { 397209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov setTablesAndProjectionMapForRawContactsEntities(qb, uri); 397309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov break; 3974a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3975a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3976a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov case RAW_CONTACT_ENTITY_ID: { 3977a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 3978a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov setTablesAndProjectionMapForRawContactsEntities(qb, uri); 3979a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 3980a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 3981a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov break; 3982a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3983a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3984a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov default: 3985a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 3986a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sortOrder, limit); 3987a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3988a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3989a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 3990a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3991a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 3992a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 3993a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 3994a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String limit) { 3995a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (projection != null && projection.length == 1 3996a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov && BaseColumns._COUNT.equals(projection[0])) { 3997a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov qb.setProjectionMap(sCountProjectionMap); 3998a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 3999a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 4000a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov sortOrder, limit); 4001a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (c != null) { 4002a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 400309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 4004bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov return c; 4005bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4006bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4007bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov private long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 4008ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 4009bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 4010bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4011ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov long contactId = lookupContactIdBySourceIds(db, segments); 4012ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (contactId == -1) { 4013bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 4014bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4015bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4016bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov return contactId; 4017de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa } 4018ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4019ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov private interface LookupBySourceIdQuery { 4020ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 4021ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4022ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String COLUMNS[] = { 4023ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov RawContacts.CONTACT_ID, 4024ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 4025ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 4026ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov RawContacts.SOURCE_ID 4027ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 4028ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4029ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int CONTACT_ID = 0; 4030ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int ACCOUNT_TYPE = 1; 4031ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int ACCOUNT_NAME = 2; 4032ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int SOURCE_ID = 3; 4033ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4034ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4035ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 4036ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 4037ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int sourceIdCount = 0; 4038ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 4039ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 4040ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (segment.sourceIdLookup) { 4041ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sourceIdCount++; 4042ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4043ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4044bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4045ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (sourceIdCount == 0) { 4046bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov return -1; 4047bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4048bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4049bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // First try sync ids 4050bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov StringBuilder sb = new StringBuilder(); 4051bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 4052bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 4053bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov LookupKeySegment segment = segments.get(i); 4054bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (segment.sourceIdLookup) { 4055bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 4056ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sb.append(","); 4057bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4058bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4059ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 4060ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 4061ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4062ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 4063f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov sb.toString(), null, null, null, null); 4064ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov try { 4065ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov while (c.moveToNext()) { 4066ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 4067ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 4068f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov int accountHashCode = 4069ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 4070ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 4071bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 4072bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov LookupKeySegment segment = segments.get(i); 4073bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (segment.sourceIdLookup && accountHashCode == segment.accountHashCode 4074bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov && segment.key.equals(sourceId)) { 4075bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 4076bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov break; 4077ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4078f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov } 4079bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4080bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } finally { 4081bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov c.close(); 4082bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4083bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4084bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov return getMostReferencedContactId(segments); 4085bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4086bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4087bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov private interface LookupByDisplayNameQuery { 4088bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 4089bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4090bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String COLUMNS[] = { 4091bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov RawContacts.CONTACT_ID, 4092bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 4093bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov RawContacts.ACCOUNT_NAME, 4094bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 4095bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov }; 4096bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4097bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int CONTACT_ID = 0; 4098ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int ACCOUNT_TYPE = 1; 4099ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int ACCOUNT_NAME = 2; 4100e2adda196b19047bc5243d2bffe9e5650e17e39dDmitri Plotnikov int NORMALIZED_NAME = 3; 4101ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4102f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov 4103ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 4104ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 4105ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int displayNameCount = 0; 41062d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill for (int i = 0; i < segments.size(); i++) { 410792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 410892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (!segment.sourceIdLookup) { 410992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov displayNameCount++; 411092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 41112d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill } 41122d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill 41135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (displayNameCount == 0) { 41145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return -1; 41155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 411692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 411792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov // First try sync ids 411892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 411992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 412092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 412192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 412292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (!segment.sourceIdLookup) { 412392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 412492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(","); 412592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 412692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 412792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 412892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 412992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 413092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 413192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 413292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.toString(), null, null, null, null); 413392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov try { 413492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov while (c.moveToNext()) { 41355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 41365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 41375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 41385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 41395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 41405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 41415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 41425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!segment.sourceIdLookup && accountHashCode == segment.accountHashCode 41435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 41445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 41455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 41465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 41505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 41515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 41545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 41575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 41585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 41595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 41605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 41615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 416392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int bestRefCount = 0; 41645870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 41665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 41675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 41695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 41705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 41715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 41725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 41735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 41745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 41755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 41765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 41775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 41785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 41805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 41815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 418292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 418392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 41845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 41855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 41865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 41875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 41885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 41905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 41915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 41925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String[] projection) { 41935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 41945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov boolean excludeRestrictedData = false; 41955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 41965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 419792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (requestingPackage != null) { 419892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 41995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(mDbHelper.getContactView(excludeRestrictedData)); 42015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (mDbHelper.isInProjection(projection, 42025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Contacts.CONTACT_PRESENCE)) { 42035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 420492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov " ON (" + Contacts._ID + " = " + AggregatedPresenceColumns.CONTACT_ID + ")"); 42055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (mDbHelper.isInProjection(projection, 42075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Contacts.CONTACT_STATUS, 42085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 42095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 421092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 42115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 42125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 421392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov + ContactsStatusUpdatesColumns.ALIAS + 421492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 421592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 421692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 42175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov qb.setTables(sb.toString()); 42185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 421992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 422092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 422192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 42225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 42235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov boolean excludeRestrictedData = false; 422492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String requestingPackage = getQueryParameter(uri, 422592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 42265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (requestingPackage != null) { 422792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 422892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 422992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(mDbHelper.getRawContactView(excludeRestrictedData)); 423092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov qb.setTables(sb.toString()); 423192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov qb.setProjectionMap(sRawContactsProjectionMap); 423292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov appendAccountFromParameter(qb, uri); 423392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 423492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 423592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private void setTablesAndProjectionMapForRawContactsEntities(SQLiteQueryBuilder qb, Uri uri) { 423692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov // Note: currently, "export only" equals to "restricted", but may not in the future. 423792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov boolean excludeRestrictedData = readBooleanQueryParameter(uri, 423892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Data.FOR_EXPORT_ONLY, false); 423992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 424092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String requestingPackage = getQueryParameter(uri, 424192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 424292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (requestingPackage != null) { 424392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov excludeRestrictedData = excludeRestrictedData 424492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 424592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 424692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov qb.setTables(mDbHelper.getContactEntitiesView(excludeRestrictedData)); 424792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov qb.setProjectionMap(sRawContactsEntityProjectionMap); 42485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov appendAccountFromParameter(qb, uri); 42495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 425092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 425192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 425292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String[] projection, boolean distinct) { 425392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 425492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov // Note: currently, "export only" equals to "restricted", but may not in the future. 425592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov boolean excludeRestrictedData = readBooleanQueryParameter(uri, 425692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Data.FOR_EXPORT_ONLY, false); 425792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 425892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String requestingPackage = getQueryParameter(uri, 425992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 426092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (requestingPackage != null) { 426192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov excludeRestrictedData = excludeRestrictedData 426292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 426392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 426492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 426592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(mDbHelper.getDataView(excludeRestrictedData)); 426692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(" data"); 426792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 426892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov // Include aggregated presence when requested 426992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (mDbHelper.isInProjection(projection, Data.CONTACT_PRESENCE)) { 427092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 42715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov " ON (" + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + "=" 42725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + RawContacts.CONTACT_ID + ")"); 42735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 427592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov // Include aggregated status updates when requested 427692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (mDbHelper.isInProjection(projection, 42775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Data.CONTACT_STATUS, 42785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Data.CONTACT_STATUS_RES_PACKAGE, 42795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Data.CONTACT_STATUS_ICON, 42805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Data.CONTACT_STATUS_LABEL, 42815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Data.CONTACT_STATUS_TIMESTAMP)) { 42825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 42835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + ContactsStatusUpdatesColumns.ALIAS + 42845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 42855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 42865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // Include individual presence when requested 42895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (mDbHelper.isInProjection(projection, Data.PRESENCE)) { 42905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 42915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov " ON (" + StatusUpdates.DATA_ID + "=" 42925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + DataColumns.CONCRETE_ID + ")"); 42935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 42945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 42955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov // Include individual status updates when requested 429692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (mDbHelper.isInProjection(projection, 429792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Data.STATUS, 429892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Data.STATUS_RES_PACKAGE, 42995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Data.STATUS_ICON, 43005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Data.STATUS_LABEL, 43015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Data.STATUS_TIMESTAMP)) { 43025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 43035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 43045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + DataColumns.CONCRETE_ID + ")"); 43055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 43075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov qb.setTables(sb.toString()); 43085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov qb.setProjectionMap(distinct ? sDistinctDataProjectionMap : sDataProjectionMap); 43095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov appendAccountFromParameter(qb, uri); 43105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 431292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 431392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String[] projection) { 431492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 431592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(mDbHelper.getDataView()); 431692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(" data"); 431792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 431892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (mDbHelper.isInProjection(projection, StatusUpdates.PRESENCE)) { 431992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 432092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov " ON(" + Tables.PRESENCE + "." + StatusUpdates.DATA_ID 432192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 432292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 4323ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov 4324ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov if (mDbHelper.isInProjection(projection, 4325ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov StatusUpdates.STATUS, 4326ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 43275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StatusUpdates.STATUS_ICON, 43285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StatusUpdates.STATUS_LABEL, 43295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 43305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 43315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov " ON(" + Tables.STATUS_UPDATES + "." + StatusUpdatesColumns.DATA_ID 43325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 43335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov qb.setTables(sb.toString()); 43355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 43365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 43385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 43395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 43405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 43415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!TextUtils.isEmpty(accountName)) { 43425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 43435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 43445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 43455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 43465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 43475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov qb.appendWhere("1"); 43485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 43515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private String appendAccountToSelection(Uri uri, String selection) { 43525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 43535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 43545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!TextUtils.isEmpty(accountName)) { 43555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 43565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 43575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 43585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 43595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (!TextUtils.isEmpty(selection)) { 43605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov selectionSb.append(" AND ("); 43615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov selectionSb.append(selection); 4362763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar selectionSb.append(')'); 4363763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 436482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov return selectionSb.toString(); 43657ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov } else { 43667ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov return selection; 43677ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov } 4368916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 4369916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 4370916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** 4371916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * Gets the value of the "limit" URI query parameter. 4372916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * 4373916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 4374916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * the parameter is not set, or is set to an invalid value. 4375916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov */ 4376916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private String getLimit(Uri uri) { 43777ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov String limitParam = getQueryParameter(uri, "limit"); 43787ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov if (limitParam == null) { 43797ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov return null; 43807ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov } 4381916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov // make sure that the limit is a non-negative integer 438203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov try { 438303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov int l = Integer.parseInt(limitParam); 438403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if (l < 0) { 438503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 438630cc766756461da8d53933f88ea01dd2272a90ebDmitri Plotnikov return null; 438730cc766756461da8d53933f88ea01dd2272a90ebDmitri Plotnikov } 43885e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov return String.valueOf(l); 43895e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } catch (NumberFormatException ex) { 43905e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 43917ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov return null; 43927ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov } 439303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 439403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 439503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov /** 4396916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * Returns true if all the characters are meaningful as digits 439703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov * in a phone number -- letters, digits, and a few punctuation marks. 439803197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov */ 4399916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private boolean isPhoneNumber(CharSequence cons) { 4400174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov int len = cons.length(); 440103197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 440203197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov for (int i = 0; i < len; i++) { 440303197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov char c = cons.charAt(i); 440403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov 440503197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov if ((c >= '0') && (c <= '9')) { 440603197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov continue; 440703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 44085e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov if ((c == ' ') || (c == '-') || (c == '(') || (c == ')') || (c == '.') || (c == '+') 44095e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov || (c == '#') || (c == '*')) { 44105e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov continue; 44115e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 44125e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov if ((c >= 'A') && (c <= 'Z')) { 44135e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov continue; 44145e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 44155e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov if ((c >= 'a') && (c <= 'z')) { 44165e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov continue; 4417174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 4418174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 4419174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return false; 4420174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 4421174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 4422174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return true; 4423174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 4424174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 4425174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov String getContactsRestrictions() { 4426174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov if (mDbHelper.hasAccessToRestrictedData()) { 4427174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return "1"; 4428174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } else { 4429174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return RawContacts.IS_RESTRICTED + "=0"; 4430174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 4431174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 4432174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 44333716f1447ceb21180d1301790eabd8b9453f486dDave Santoro public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 44343716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (mDbHelper.hasAccessToRestrictedData()) { 44353716f1447ceb21180d1301790eabd8b9453f486dDave Santoro return "1"; 44363716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } else { 4437174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 4438174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 4439174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 4440174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 4441174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 444204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann @Override 444304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 444404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann int match = sUriMatcher.match(uri); 444504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann switch (match) { 444604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann case CONTACTS_PHOTO: { 4447174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov if (!"r".equals(mode)) { 4448174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov throw new FileNotFoundException("Mode " + mode + " not supported."); 4449174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov } 4450174f7d319b987aa2aeeb6f2563f4b939acb8d791Dmitri Plotnikov 44515e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov String sql = 44525e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mDbHelper.getDataView() + 44533d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov " WHERE " + Data._ID + "=" + Contacts.PHOTO_ID 44545e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + "=?"; 445504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann SQLiteDatabase db = mDbHelper.getReadableDatabase(); 445604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann return SQLiteContentHelper.getBlobColumnAsAssetFile(db, sql, 445704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann new String[]{uri.getPathSegments().get(1)}); 445804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 445904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann 446004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann case CONTACTS_AS_VCARD: { 44613d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov final String lookupKey = uri.getPathSegments().get(2); 44623d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 44633716f1447ceb21180d1301790eabd8b9453f486dDave Santoro final String selection = Contacts._ID + "=" + contactId; 44643716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 44653716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // When opening a contact as file, we pass back contents as a 44663716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // vCard-encoded stream. We build into a local buffer first, 44673716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // then pipe into MemoryFile once the exact size is known. 44683716f1447ceb21180d1301790eabd8b9453f486dDave Santoro final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 44693716f1447ceb21180d1301790eabd8b9453f486dDave Santoro outputRawContactsAsVCard(localStream, selection, null); 44703d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov return buildAssetFileDescriptor(localStream); 44713d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov } 44723d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov 44733d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov default: 447404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann throw new FileNotFoundException("No file at: " + uri); 447504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 447604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 447704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann 447804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 447904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann private static final String VCARD_TYPE_DEFAULT = "default"; 448004f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann 448104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann /** 448204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann * Build a {@link AssetFileDescriptor} through a {@link MemoryFile} with the 448304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann * contents of the given {@link ByteArrayOutputStream}. 448404f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann */ 448504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 448604f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann AssetFileDescriptor fd = null; 448704f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann try { 448804f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann stream.flush(); 448904f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann 44905e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov final byte[] byteData = stream.toByteArray(); 44915e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov final int size = byteData.length; 44923716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 44933716f1447ceb21180d1301790eabd8b9453f486dDave Santoro final MemoryFile memoryFile = new MemoryFile(CONTACT_MEMORY_FILE_NAME, size); 44943716f1447ceb21180d1301790eabd8b9453f486dDave Santoro memoryFile.writeBytes(byteData, 0, 0, size); 44953716f1447ceb21180d1301790eabd8b9453f486dDave Santoro memoryFile.deactivate(); 44963716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 44973716f1447ceb21180d1301790eabd8b9453f486dDave Santoro fd = AssetFileDescriptor.fromMemoryFile(memoryFile); 44983716f1447ceb21180d1301790eabd8b9453f486dDave Santoro } catch (IOException e) { 44995e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov Log.w(TAG, "Problem writing stream into an AssetFileDescriptor: " + e.toString()); 450003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov } 450104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann return fd; 450204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 45033716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 45043716f1447ceb21180d1301790eabd8b9453f486dDave Santoro /** 45053716f1447ceb21180d1301790eabd8b9453f486dDave Santoro * Output {@link RawContacts} matching the requested selection in the vCard 45063716f1447ceb21180d1301790eabd8b9453f486dDave Santoro * format to the given {@link OutputStream}. This method returns silently if 45073716f1447ceb21180d1301790eabd8b9453f486dDave Santoro * any errors encountered. 45083716f1447ceb21180d1301790eabd8b9453f486dDave Santoro */ 45093716f1447ceb21180d1301790eabd8b9453f486dDave Santoro private void outputRawContactsAsVCard(OutputStream stream, String selection, 45103716f1447ceb21180d1301790eabd8b9453f486dDave Santoro String[] selectionArgs) { 45113716f1447ceb21180d1301790eabd8b9453f486dDave Santoro final Context context = this.getContext(); 45123716f1447ceb21180d1301790eabd8b9453f486dDave Santoro final VCardComposer composer = new VCardComposer(context, VCARD_TYPE_DEFAULT, false); 45133716f1447ceb21180d1301790eabd8b9453f486dDave Santoro composer.addHandler(composer.new HandlerForOutputStream(stream)); 45143716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 45153716f1447ceb21180d1301790eabd8b9453f486dDave Santoro // No extra checks since composer always uses restricted views 45163716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (!composer.init(selection, selectionArgs)) 45173716f1447ceb21180d1301790eabd8b9453f486dDave Santoro return; 45183716f1447ceb21180d1301790eabd8b9453f486dDave Santoro 45193716f1447ceb21180d1301790eabd8b9453f486dDave Santoro while (!composer.isAfterLast()) { 45203716f1447ceb21180d1301790eabd8b9453f486dDave Santoro if (!composer.createOneEntry()) { 452104f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann Log.w(TAG, "Failed to output a contact."); 452204f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 452304f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann } 452403197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov composer.terminate(); 45255e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov } 45265e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 452703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov /** 45285e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov * An implementation of EntityIterator that joins the contacts and data tables 45295e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov * and consumes all the data rows for a contact in order to build the Entity for a contact. 45305e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov */ 45315e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov private static class RawContactsEntityIterator implements EntityIterator { 45322352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov private final Cursor mEntityCursor; 45333d0f0e0a1325ae306842b3ad1487d3507df0821dDmitri Plotnikov private volatile boolean mIsClosed; 45342352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov 453504f7fc0bddad198108d2f45cb730b9506e81dedbDaniel Lehmann private static final String[] DATA_KEYS = new String[]{ 45362352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov Data.DATA1, 453703197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov Data.DATA2, 45382352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov Data.DATA3, 45399c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov Data.DATA4, 454003197a00e17386aa9b1971bde3cda034bc17e0c3Dmitri Plotnikov Data.DATA5, 4541a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov Data.DATA6, 4542a1e177389debb74a51587720464a527a193bffc1Dmitri Plotnikov Data.DATA7, 45432352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov Data.DATA8, 45442352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov Data.DATA9, 45452352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov Data.DATA10, 45462352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov Data.DATA11, 45472352cf62c46e1caaad64c7b3dbcc601951018eb3Dmitri Plotnikov Data.DATA12, 45485e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov Data.DATA13, 45495e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov Data.DATA14, 45505e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov Data.DATA15, 45515e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov Data.SYNC1, 45525e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov Data.SYNC2, 45535e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov Data.SYNC3, 45545e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov Data.SYNC4}; 45555e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov 45565e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov public static final String[] PROJECTION = new String[]{ 45575e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov RawContacts.ACCOUNT_NAME, 45585e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 45595e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov RawContacts.SOURCE_ID, 45605e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov RawContacts.VERSION, 45615e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov RawContacts.DIRTY, 45625e70c0772ef2b975c95787112ac0f15047a4ff0cDmitri Plotnikov RawContacts.Entity.DATA_ID, 4563763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar Data.RES_PACKAGE, 4564763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar Data.MIMETYPE, 45657ba290f5de7f116ec0eaac30980ffef2878d2b64Dmitri Plotnikov Data.DATA1, 4566763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar Data.DATA2, 4567763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar Data.DATA3, 4568763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar Data.DATA4, 4569763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar Data.DATA5, 4570763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar Data.DATA6, 4571a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.DATA7, 4572a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.DATA8, 4573a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.DATA9, 457446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Data.DATA10, 457546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Data.DATA11, 457646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Data.DATA12, 457782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.DATA13, 457882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.DATA14, 457982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.DATA15, 4580a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.SYNC1, 458182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.SYNC2, 458282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.SYNC3, 4583a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.SYNC4, 4584a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov RawContacts._ID, 4585a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.IS_PRIMARY, 4586a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Data.IS_SUPER_PRIMARY, 45873296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.DATA_VERSION, 458882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov GroupMembership.GROUP_SOURCE_ID, 4589f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.SYNC1, 4590f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.SYNC2, 4591f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.SYNC3, 4592f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.SYNC4, 4593f4e7ae68ba58d82b16bc2101db8d0f358c1d9297Dmitri Plotnikov RawContacts.DELETED, 459482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov RawContacts.CONTACT_ID, 4595ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov RawContacts.STARRED, 4596ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov RawContacts.IS_RESTRICTED}; 45970a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 45980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private static final int COLUMN_ACCOUNT_NAME = 0; 45990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private static final int COLUMN_ACCOUNT_TYPE = 1; 4600b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private static final int COLUMN_SOURCE_ID = 2; 46010a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private static final int COLUMN_VERSION = 3; 4602a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_DIRTY = 4; 4603a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_DATA_ID = 5; 46040a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private static final int COLUMN_RES_PACKAGE = 6; 4605a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_MIMETYPE = 7; 4606a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_DATA1 = 8; 4607a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_RAW_CONTACT_ID = 27; 4608a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_IS_PRIMARY = 28; 4609a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_IS_SUPER_PRIMARY = 29; 4610a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_DATA_VERSION = 30; 4611a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_GROUP_SOURCE_ID = 31; 4612a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_SYNC1 = 32; 4613a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_SYNC2 = 33; 4614a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_SYNC3 = 34; 4615a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_SYNC4 = 35; 4616a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_DELETED = 36; 4617a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_CONTACT_ID = 37; 4618a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_STARRED = 38; 4619a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov private static final int COLUMN_IS_RESTRICTED = 39; 4620a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4621a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov public RawContactsEntityIterator(ContactsProvider2 provider, Uri entityUri, 4622a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String contactsIdString, 4623a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String selection, String[] selectionArgs, String sortOrder) { 4624a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov mIsClosed = false; 4625a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Uri uri; 4626a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (contactsIdString != null) { 4627a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov uri = Uri.withAppendedPath(RawContacts.CONTENT_URI, contactsIdString); 4628a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov uri = Uri.withAppendedPath(uri, RawContacts.Entity.CONTENT_DIRECTORY); 4629a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } else { 4630a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov uri = ContactsContract.RawContactsEntity.CONTENT_URI; 4631a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4632a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov final Uri.Builder builder = uri.buildUpon(); 4633a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov String query = entityUri.getQuery(); 4634a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov builder.encodedQuery(query); 4635a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov mEntityCursor = provider.query(builder.build(), 4636a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov PROJECTION, selection, selectionArgs, sortOrder); 46370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mEntityCursor.moveToFirst(); 4638a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 46390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 4640a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov public void reset() throws RemoteException { 4641a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (mIsClosed) { 4642b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov throw new IllegalStateException("calling reset() when the iterator is closed"); 46430a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 46440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mEntityCursor.moveToFirst(); 46450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 46460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 46470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov public void close() { 46480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (mIsClosed) { 4649a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov throw new IllegalStateException("closing when already closed"); 4650a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 46510a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mIsClosed = true; 4652a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov mEntityCursor.close(); 4653a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4654a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4655a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov public boolean hasNext() throws RemoteException { 4656a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (mIsClosed) { 4657a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov throw new IllegalStateException("calling hasNext() when the iterator is closed"); 4658a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4659a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4660a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov return !mEntityCursor.isAfterLast(); 4661a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4662a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4663a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov public Entity next() throws RemoteException { 4664a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (mIsClosed) { 4665a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov throw new IllegalStateException("calling next() when the iterator is closed"); 4666a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4667a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (!hasNext()) { 4668a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov throw new IllegalStateException("you may only call next() if hasNext() is true"); 4669a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov } 4670a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4671a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 4672385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov 4673385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov final long rawContactId = c.getLong(COLUMN_RAW_CONTACT_ID); 4674385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov 4675385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov // we expect the cursor is already at the row we need to read from 4676385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov ContentValues contactValues = new ContentValues(); 4677385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 4678385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 4679385182830ff0ed84edce9aba2424d2afe99453ceDmitri Plotnikov contactValues.put(RawContacts._ID, rawContactId); 4680a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov contactValues.put(RawContacts.DIRTY, c.getLong(COLUMN_DIRTY)); 4681a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov contactValues.put(RawContacts.VERSION, c.getLong(COLUMN_VERSION)); 4682a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov contactValues.put(RawContacts.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 4683a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov contactValues.put(RawContacts.SYNC1, c.getString(COLUMN_SYNC1)); 4684a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov contactValues.put(RawContacts.SYNC2, c.getString(COLUMN_SYNC2)); 4685a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov contactValues.put(RawContacts.SYNC3, c.getString(COLUMN_SYNC3)); 4686a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov contactValues.put(RawContacts.SYNC4, c.getString(COLUMN_SYNC4)); 4687a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov contactValues.put(RawContacts.DELETED, c.getLong(COLUMN_DELETED)); 4688a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov contactValues.put(RawContacts.CONTACT_ID, c.getLong(COLUMN_CONTACT_ID)); 4689a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov contactValues.put(RawContacts.STARRED, c.getLong(COLUMN_STARRED)); 4690a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov contactValues.put(RawContacts.IS_RESTRICTED, c.getInt(COLUMN_IS_RESTRICTED)); 4691a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov Entity contact = new Entity(contactValues); 4692a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov 4693a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov // read data rows until the contact id changes 4694a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov do { 46950a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (rawContactId != c.getLong(COLUMN_RAW_CONTACT_ID)) { 46960a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov break; 46974a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 4698f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov// if (c.isNull(COLUMN_CONTACT_ID)) { 4699f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov// continue; 4700e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey// } 4701e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // add the data to to the contact 4702e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ContentValues dataValues = new ContentValues(); 4703e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey dataValues.put(Data._ID, c.getLong(COLUMN_DATA_ID)); 4704fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov dataValues.put(Data.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 4705fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov dataValues.put(Data.MIMETYPE, c.getString(COLUMN_MIMETYPE)); 4706e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey dataValues.put(Data.IS_PRIMARY, c.getLong(COLUMN_IS_PRIMARY)); 4707e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey dataValues.put(Data.IS_SUPER_PRIMARY, c.getLong(COLUMN_IS_SUPER_PRIMARY)); 4708e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 4709e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (!c.isNull(COLUMN_GROUP_SOURCE_ID)) { 4710e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey dataValues.put(GroupMembership.GROUP_SOURCE_ID, 4711e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey c.getString(COLUMN_GROUP_SOURCE_ID)); 47124a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 47134a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 47144a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov for (int i = 0; i < DATA_KEYS.length; i++) { 47154a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov final int columnIndex = i + COLUMN_DATA1; 47164a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String key = DATA_KEYS[i]; 47174a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c.isNull(columnIndex)) { 47184a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // don't put anything 47194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else if (c.isLong(columnIndex)) { 47204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov dataValues.put(key, c.getLong(columnIndex)); 4721e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else if (c.isFloat(columnIndex)) { 4722f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov dataValues.put(key, c.getFloat(columnIndex)); 4723f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else if (c.isString(columnIndex)) { 4724e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey dataValues.put(key, c.getString(columnIndex)); 4725e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (c.isBlob(columnIndex)) { 4726e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey dataValues.put(key, c.getBlob(columnIndex)); 4727e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 4728fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov } 4729fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov contact.addSubValue(Data.CONTENT_URI, dataValues); 4730e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } while (mEntityCursor.moveToNext()); 4731e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4732e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return contact; 4733e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 4734e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 4735e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 4736e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong /** 4737e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong * An implementation of EntityIterator that joins the contacts and data tables 4738e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong * and consumes all the data rows for a contact in order to build the Entity for a contact. 4739e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong */ 4740e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private static class GroupsEntityIterator implements EntityIterator { 4741e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private final Cursor mEntityCursor; 4742e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private volatile boolean mIsClosed; 4743e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 4744e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private static final String[] PROJECTION = new String[]{ 4745e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong Groups._ID, 4746e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong Groups.ACCOUNT_NAME, 4747e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong Groups.ACCOUNT_TYPE, 4748e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong Groups.SOURCE_ID, 4749e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong Groups.DIRTY, 4750e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong Groups.VERSION, 47517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana Groups.RES_PACKAGE, 4752c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Groups.TITLE, 4753c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Groups.TITLE_RES, 4754c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Groups.GROUP_VISIBLE, 4755c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Groups.SYNC1, 4756c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Groups.SYNC2, 4757f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov Groups.SYNC3, 47582e40e351a80ff608045bc9f55b48bd1a3d16926bDmitri Plotnikov Groups.SYNC4, 4759c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Groups.SYSTEM_ID, 4760c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Groups.NOTES, 4761c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Groups.DELETED, 4762c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Groups.SHOULD_SYNC}; 4763c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4764c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int COLUMN_ID = 0; 4765c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int COLUMN_ACCOUNT_NAME = 1; 4766c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int COLUMN_ACCOUNT_TYPE = 2; 4767c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int COLUMN_SOURCE_ID = 3; 4768c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int COLUMN_DIRTY = 4; 4769c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int COLUMN_VERSION = 5; 4770c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int COLUMN_RES_PACKAGE = 6; 4771c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int COLUMN_TITLE = 7; 4772c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int COLUMN_TITLE_RES = 8; 4773c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int COLUMN_GROUP_VISIBLE = 9; 4774c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int COLUMN_SYNC1 = 10; 4775c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int COLUMN_SYNC2 = 11; 477600ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey private static final int COLUMN_SYNC3 = 12; 4777d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton private static final int COLUMN_SYNC4 = 13; 477870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov private static final int COLUMN_SYSTEM_ID = 14; 477970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov private static final int COLUMN_NOTES = 15; 4780fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov private static final int COLUMN_DELETED = 16; 478170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov private static final int COLUMN_SHOULD_SYNC = 17; 478270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 478370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public GroupsEntityIterator(ContactsProvider2 provider, String groupIdString, Uri uri, 478470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder) { 4785d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton mIsClosed = false; 478670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 478767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String updatedSortOrder = (sortOrder == null) 47885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov ? Groups._ID 47895ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov : (Groups._ID + "," + sortOrder); 4790619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4791619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final SQLiteDatabase db = provider.mDbHelper.getReadableDatabase(); 4792619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 4793b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov qb.setTables(provider.mDbHelper.getGroupView()); 4794f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert qb.setProjectionMap(sGroupsProjectionMap); 4795415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov if (groupIdString != null) { 4796415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov qb.appendWhere(Groups._ID + "=" + groupIdString); 4797415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov } 4798b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov final String accountName = getQueryParameter(uri, Groups.ACCOUNT_NAME); 4799b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov final String accountType = getQueryParameter(uri, Groups.ACCOUNT_TYPE); 4800a549eb3c9627862a3e45d910d5c981191086a949Dmitri Plotnikov if (!TextUtils.isEmpty(accountName)) { 4801f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert qb.appendWhere(Groups.ACCOUNT_NAME + "=" 4802e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 4803e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov + Groups.ACCOUNT_TYPE + "=" 4804e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 4805b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 4806e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 4807f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert null, null, updatedSortOrder); 4808e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov mEntityCursor.moveToFirst(); 48094da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 4810d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4811d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey public void close() { 4812f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey if (mIsClosed) { 481349d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov throw new IllegalStateException("closing when already closed"); 481442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 481549d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov mIsClosed = true; 481642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann mEntityCursor.close(); 481742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 481842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 481942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann public boolean hasNext() throws RemoteException { 482042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann if (mIsClosed) { 482142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann throw new IllegalStateException("calling hasNext() when the iterator is closed"); 482242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 4823f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 482442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann return !mEntityCursor.isAfterLast(); 482542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 482642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 482749d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov public void reset() throws RemoteException { 482842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann if (mIsClosed) { 482942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann throw new IllegalStateException("calling reset() when the iterator is closed"); 483042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 483142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann mEntityCursor.moveToFirst(); 4832d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann } 4833d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann 483442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann public Entity next() throws RemoteException { 483542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann if (mIsClosed) { 4836d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann throw new IllegalStateException("calling next() when the iterator is closed"); 483742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 4838d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann if (!hasNext()) { 483942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann throw new IllegalStateException("you may only call next() if hasNext() is true"); 484049d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov } 484142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 484242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 484342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 484442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final long groupId = c.getLong(COLUMN_ID); 4845d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4846d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // we expect the cursor is already at the row we need to read from 4847d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey ContentValues groupValues = new ContentValues(); 4848d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey groupValues.put(Groups.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 4849d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey groupValues.put(Groups.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 4850d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann groupValues.put(Groups._ID, groupId); 4851f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert groupValues.put(Groups.DIRTY, c.getLong(COLUMN_DIRTY)); 4852d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey groupValues.put(Groups.VERSION, c.getLong(COLUMN_VERSION)); 4853b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov groupValues.put(Groups.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 4854b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov groupValues.put(Groups.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 4855fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov groupValues.put(Groups.TITLE, c.getString(COLUMN_TITLE)); 4856fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov groupValues.put(Groups.TITLE_RES, c.getString(COLUMN_TITLE_RES)); 4857b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov groupValues.put(Groups.GROUP_VISIBLE, c.getLong(COLUMN_GROUP_VISIBLE)); 4858b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov groupValues.put(Groups.SYNC1, c.getString(COLUMN_SYNC1)); 4859b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov groupValues.put(Groups.SYNC2, c.getString(COLUMN_SYNC2)); 4860f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert groupValues.put(Groups.SYNC3, c.getString(COLUMN_SYNC3)); 4861e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov groupValues.put(Groups.SYNC4, c.getString(COLUMN_SYNC4)); 4862e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov groupValues.put(Groups.SYSTEM_ID, c.getString(COLUMN_SYSTEM_ID)); 4863e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov groupValues.put(Groups.DELETED, c.getLong(COLUMN_DELETED)); 4864e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov groupValues.put(Groups.NOTES, c.getString(COLUMN_NOTES)); 4865e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov groupValues.put(Groups.SHOULD_SYNC, c.getString(COLUMN_SHOULD_SYNC)); 4866e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov Entity group = new Entity(groupValues); 4867e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 4868e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov mEntityCursor.moveToNext(); 4869e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 4870e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov return group; 4871e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 487208ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood } 4873f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 4874f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert @Override 487508ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs, 487608ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood String sortOrder) { 487708ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood waitForAccess(); 487808ee3fb4e82900b52d02627ed54907431f4f5adeMathew Inwood 4879e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov final int match = sUriMatcher.match(uri); 4880e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov switch (match) { 4881d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case RAW_CONTACTS: 4882d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case RAW_CONTACTS_ID: 4883d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String contactsIdString = null; 4884f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert if (match == RAW_CONTACTS_ID) { 4885d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey contactsIdString = uri.getPathSegments().get(1); 4886d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4887f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 4888d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return new RawContactsEntityIterator(this, uri, contactsIdString, 4889d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey selection, selectionArgs, sortOrder); 4890d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case GROUPS: 4891d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case GROUPS_ID: 4892d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String idString = null; 4893f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert if (match == GROUPS_ID) { 4894f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert idString = uri.getPathSegments().get(1); 4895f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 4896d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 4897ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert return new GroupsEntityIterator(this, idString, 4898ac13ddd04d665442de846b59234bdc936a6699b4Bjorn Bringert uri, selection, selectionArgs, sortOrder); 4899d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey default: 4900d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey throw new UnsupportedOperationException("Unknown uri: " + uri); 4901d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 4902f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert } 4903f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert 4904f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert @Override 4905f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert public String getType(Uri uri) { 4906f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert final int match = sUriMatcher.match(uri); 4907f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert switch (match) { 4908f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert case CONTACTS: 4909f87d3f35a3759d5b95a403c2539859e1b3ee429fBjorn Bringert case CONTACTS_LOOKUP: 4910d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return Contacts.CONTENT_TYPE; 4911d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_ID: 4912d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_LOOKUP_ID: 4913d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return Contacts.CONTENT_ITEM_TYPE; 4914d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_AS_VCARD: 4915d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 4916d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case RAW_CONTACTS: 4917d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return RawContacts.CONTENT_TYPE; 49187a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa case RAW_CONTACTS_ID: 49197a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa return RawContacts.CONTENT_ITEM_TYPE; 4920108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa case DATA_ID: 4921108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return mDbHelper.getDataMimeType(ContentUris.parseId(uri)); 4922108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa case PHONES: 4923108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return Phone.CONTENT_TYPE; 4924108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa case PHONES_ID: 4925108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return Phone.CONTENT_ITEM_TYPE; 4926108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa case EMAILS: 4927108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return Email.CONTENT_TYPE; 4928d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case EMAILS_ID: 4929108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return Email.CONTENT_ITEM_TYPE; 4930108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa case POSTALS: 4931108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return StructuredPostal.CONTENT_TYPE; 4932108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa case POSTALS_ID: 4933108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return StructuredPostal.CONTENT_ITEM_TYPE; 4934108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa case AGGREGATION_EXCEPTIONS: 4935108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return AggregationExceptions.CONTENT_TYPE; 4936108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa case AGGREGATION_EXCEPTION_ID: 4937108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return AggregationExceptions.CONTENT_ITEM_TYPE; 4938108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa case SETTINGS: 4939108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return Settings.CONTENT_TYPE; 4940108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa case AGGREGATION_SUGGESTIONS: 4941108f1be6b0e855f1b335bc591755a9e5f488175aDaisuke Miyakawa return Contacts.CONTENT_TYPE; 4942d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case SEARCH_SUGGESTIONS: 4943d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return SearchManager.SUGGEST_MIME_TYPE; 4944d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case SEARCH_SHORTCUT: 4945b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 49464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 49474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return mLegacyApiSupport.getType(uri); 4948415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov } 4949415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov } 4950415ba9ec45dc1be35d3921b28e1dae23e150fb25Dmitri Plotnikov 4951a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private void setDisplayName(long rawContactId, String displayName, int bestDisplayNameSource) { 49524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (displayName != null) { 4953b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov mRawContactDisplayNameUpdate.bindString(1, displayName); 4954be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov } else { 49552d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill mRawContactDisplayNameUpdate.bindNull(1); 4956b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov } 4957b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(2, bestDisplayNameSource); 4958b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(3, rawContactId); 4959f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey mRawContactDisplayNameUpdate.execute(); 496042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 4961f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 4962f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov /** 4963f06a42ca707b8c74d0ac9070db5f9767f4fe74ddDmitri Plotnikov * Sets the {@link RawContacts#DIRTY} for the specified raw contact. 4964b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov */ 4965be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov private void setRawContactDirty(long rawContactId) { 4966b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov mDirtyRawContacts.add(rawContactId); 4967b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov } 4968f481f22a9323fe338672f99b88b26c5f0725cd42David Brown 4969f481f22a9323fe338672f99b88b26c5f0725cd42David Brown /* 4970508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey * Sets the given dataId record in the "data" table to primary, and resets all data records of 4971b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov * the same mimetype and under the same contact to not be primary. 497248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov * 497348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov * @param dataId the id of the data record to be set to primary. 497448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov */ 497548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { 49769005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov mSetPrimaryStatement.bindLong(1, dataId); 49779005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov mSetPrimaryStatement.bindLong(2, mimeTypeId); 497848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov mSetPrimaryStatement.bindLong(3, rawContactId); 497948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov mSetPrimaryStatement.execute(); 498048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 498148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 498248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov /* 498348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov * Sets the given dataId record in the "data" table to "super primary", and resets all data 498448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov * records of the same mimetype and under the same aggregate to not be "super primary". 498548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov * 4986b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov * @param dataId the id of the data record to be set to primary. 4987b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov */ 4988b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov private void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) { 4989b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov mSetSuperPrimaryStatement.bindLong(1, dataId); 4990b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov mSetSuperPrimaryStatement.bindLong(2, mimeTypeId); 4991b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov mSetSuperPrimaryStatement.bindLong(3, rawContactId); 4992b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov mSetSuperPrimaryStatement.execute(); 4993b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov } 4994c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4995c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov public void insertNameLookupForEmail(long rawContactId, long dataId, String email) { 4996c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (TextUtils.isEmpty(email)) { 4997c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return; 4998d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov } 4999d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov 5000d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email); 5001d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov if (tokens.length == 0) { 500261efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return; 500361efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov } 50044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 50054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String address = tokens[0].getAddress(); 50067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana int at = address.indexOf('@'); 500709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov if (at != -1) { 500809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov address = address.substring(0, at); 500909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 501009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 501109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov insertNameLookup(rawContactId, dataId, 501209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address)); 501309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 501409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 501509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov /** 501609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov * Normalizes the nickname and inserts it in the name lookup table. 50178727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov */ 50188727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) { 50198727a729d5c0e875538025f0a85b3ac64c3a7745Dmitri Plotnikov if (TextUtils.isEmpty(nickname)) { 502009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov return; 502109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 502209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 502309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov insertNameLookup(rawContactId, dataId, 502409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov NameLookupType.NICKNAME, NameNormalizer.normalize(nickname)); 502509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 502609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 502709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov public void insertNameLookupForOrganization(long rawContactId, long dataId, String company, 502809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov String title) { 502909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov if (!TextUtils.isEmpty(company)) { 503009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov insertNameLookup(rawContactId, dataId, 503109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov NameLookupType.ORGANIZATION, NameNormalizer.normalize(company)); 503209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 503309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov if (!TextUtils.isEmpty(title)) { 503409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov insertNameLookup(rawContactId, dataId, 503509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov NameLookupType.ORGANIZATION, NameNormalizer.normalize(title)); 503609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 503709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 503809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 503909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov public void insertNameLookupForStructuredName(long rawContactId, long dataId, String name) { 504009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name); 504109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 504209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 504309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov private interface NicknameLookupPreloadQuery { 504409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov String TABLE = Tables.NICKNAME_LOOKUP; 504509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 504609ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov String[] COLUMNS = new String[] { 504709ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov NicknameLookupColumns.NAME 504809ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov }; 504909ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 505009ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov int NAME = 0; 505109ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov } 505209ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov 505309ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov /** 505409ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov * Read all known common nicknames from the database and populate a Bloom 505509ae48b82b17e24016b14a1ab64706222ab1071fDmitri Plotnikov * filter using the corresponding hash codes. The idea is to eliminate most 5056f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * of unnecessary database lookups for nicknames. Given a name, we will take 5057f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * its hash code and see if it is set in the Bloom filter. If not, we will know 5058f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * that the name is not in the database. If it is, we still need to run a 5059f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * query. 5060f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * <p> 5061f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Given the size of the filter and the expected size of the nickname table, 5062f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * we should expect the combination of the Bloom filter and cache will 5063f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * prevent around 98-99% of unnecessary queries from running. 5064f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 506578fb53bfd973760996fe3a5fe260b1d367574de6Dmitri Plotnikov private void preloadNicknameBloomFilter() { 5066f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNicknameBloomFilter = new BitSet(NICKNAME_BLOOM_FILTER_SIZE + 1); 5067f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 5068f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Cursor cursor = db.query(NicknameLookupPreloadQuery.TABLE, 5069f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NicknameLookupPreloadQuery.COLUMNS, 5070d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov null, null, null, null, null); 5071f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov try { 5072f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int count = cursor.getCount(); 5073f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov for (int i = 0; i < count; i++) { 50742d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov cursor.moveToNext(); 5075d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov String normalizedName = cursor.getString(NicknameLookupPreloadQuery.NAME); 5076d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov int hashCode = normalizedName.hashCode(); 5077d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov mNicknameBloomFilter.set(hashCode & NICKNAME_BLOOM_FILTER_SIZE); 5078d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov } 5079d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov } finally { 5080d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov cursor.close(); 5081d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov } 5082e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 5083916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5084916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5085e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov /** 5086e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov * Returns nickname cluster IDs or null. Maintains cache. 50879a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov */ 50889a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 50899a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov int hashCode = normalizedName.hashCode(); 50909a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (!mNicknameBloomFilter.get(hashCode & NICKNAME_BLOOM_FILTER_SIZE)) { 50919a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return null; 50929a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 50939a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 50949a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov SoftReference<String[]> ref; 50959a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov String[] clusters = null; 50969a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov synchronized (mNicknameClusterCache) { 50979a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (mNicknameClusterCache.containsKey(normalizedName)) { 50989a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov ref = mNicknameClusterCache.get(normalizedName); 50999a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov if (ref == null) { 51009a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return null; 51019a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 51024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov clusters = ref.get(); 51037a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 51047a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 51057a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 51067a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (clusters == null) { 51077a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov clusters = loadNicknameClusters(normalizedName); 51087a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov ref = clusters == null ? null : new SoftReference<String[]>(clusters); 51097a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov synchronized (mNicknameClusterCache) { 51107a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov mNicknameClusterCache.put(normalizedName, ref); 51117a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 51127a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 5113f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov return clusters; 5114f6d4922f664127d0455b45b1f7444c4553581282Dmitri Plotnikov } 51157a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 51167a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private interface NicknameLookupQuery { 51177a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov String TABLE = Tables.NICKNAME_LOOKUP; 51187a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 51197a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov String[] COLUMNS = new String[] { 51207a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov NicknameLookupColumns.CLUSTER 51217a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov }; 51227a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 51237a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov int CLUSTER = 0; 51247a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 51257a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 51267a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov protected String[] loadNicknameClusters(String normalizedName) { 51277a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 51287a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov String[] clusters = null; 51297a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov Cursor cursor = db.query(NicknameLookupQuery.TABLE, NicknameLookupQuery.COLUMNS, 51307a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov NicknameLookupColumns.NAME + "=?", new String[] { normalizedName }, 51317a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov null, null, null); 51327a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov try { 51337a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov int count = cursor.getCount(); 51347a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov if (count > 0) { 51357a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov clusters = new String[count]; 51367a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov for (int i = 0; i < count; i++) { 51377a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov cursor.moveToNext(); 51387a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov clusters[i] = cursor.getString(NicknameLookupQuery.CLUSTER); 51397a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 51407a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 51417a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } finally { 51427a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov cursor.close(); 51437a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 51447a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov return clusters; 51457a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov } 51467a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 51477a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 51487a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov 51497a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 51507a3c645fa7db38449d34eb04d4e032fd079c3244Dmitri Plotnikov super(splitter); 51514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 51524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 51534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov @Override 5154b67163a1088f09c59f324350662eb18772fac6b6Evan Millar protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 5155b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String name) { 5156b67163a1088f09c59f324350662eb18772fac6b6Evan Millar ContactsProvider2.this.insertNameLookup(rawContactId, dataId, lookupType, name); 5157b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5158b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 51594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov @Override 51604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 5161b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return ContactsProvider2.this.getCommonNicknameClusters(normalizedName); 5162b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5163b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5164caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 51655e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** 51665e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar * Inserts a record in the {@link Tables#NAME_LOOKUP} table. 51675e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar */ 51685e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) { 51695e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 1, rawContactId); 51705e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 2, dataId); 51715e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 3, lookupType); 51725e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar DatabaseUtils.bindObjectToProgram(mNameLookupInsert, 4, name); 51735e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar mNameLookupInsert.executeInsert(); 51745e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 51755e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 5176caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov /** 5177caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element. 5178caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov */ 51795f1f4a062ac34d75d2dbf586702cbeb121cf09caDmitri Plotnikov public void deleteNameLookup(long dataId) { 5180caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov DatabaseUtils.bindObjectToProgram(mNameLookupDelete, 1, dataId); 5181caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov mNameLookupDelete.execute(); 5182caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 5183caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 51846f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 5185caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov sb.append("(" + 51866f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 5187caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 5188f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 518973f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 519073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 519173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov " WHERE normalized_name GLOB '"); 519273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 5193bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN(" 5194bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov + NameLookupType.NAME_COLLATION_KEY + "," 5195bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov + NameLookupType.EMAIL_BASED_NICKNAME + "," 5196bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov + NameLookupType.NICKNAME + "," 519773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov + NameLookupType.ORGANIZATION + "))"); 519873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 519973f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 520073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 520173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5202627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam, null); 5203627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov return sb.toString(); 5204627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5205627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 520673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam, 520773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov String limit) { 520873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), limit, 5209627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov true); 5210627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 5211627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 5212627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 5213627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String limit, boolean allowEmailMatch) { 521473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov sb.append("(" + 521573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov "SELECT DISTINCT " + NameLookupColumns.RAW_CONTACT_ID + 521673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 521773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 521873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov " GLOB '"); 521973f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov sb.append(normalizedName); 522073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 5221627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov + NameLookupType.NAME_COLLATION_KEY + "," 5222b4e61e064b59e8076df81b061add9fb358fd2ed9Dmitri Plotnikov + NameLookupType.NICKNAME + "," 5223d3d812af96f7d77e13dc60652626b39f25907147Dmitri Plotnikov + NameLookupType.ORGANIZATION); 5224f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (allowEmailMatch) { 5225f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov sb.append("," + NameLookupType.EMAIL_BASED_NICKNAME); 5226f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5227f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov sb.append(")"); 5228f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5229f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (limit != null) { 5230f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov sb.append(" LIMIT ").append(limit); 5231f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5232f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov sb.append(")"); 5233f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5234f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5235f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /** 5236f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 5237f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov */ 5238f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 5239f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (selectionArgs == null) { 5240f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return new String[] {arg}; 5241f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 5242f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int newLength = selectionArgs.length + 1; 5243f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String[] newSelectionArgs = new String[newLength]; 5244f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov newSelectionArgs[0] = arg; 5245f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 5246f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return newSelectionArgs; 5247f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5248f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5249f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5250f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String[] appendProjectionArg(String[] projection, String arg) { 5251f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (projection == null) { 5252f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 5253f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5254f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final int length = projection.length; 5255f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String[] newProjection = new String[length + 1]; 5256f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov System.arraycopy(projection, 0, newProjection, 0, length); 5257f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov newProjection[length] = arg; 5258f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return newProjection; 5259f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5260f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5261f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov protected Account getDefaultAccount() { 5262f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 5263f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov try { 5264f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 5265f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 5266f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (accounts != null && accounts.length > 0) { 5267f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return accounts[0]; 5268f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 52695fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa } catch (Throwable e) { 52705fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 52715fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa } 52725fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa return null; 52735fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa } 52745fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa 52755fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa protected boolean isWritableAccount(Account account) { 52765fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa IContentService contentService = ContentResolver.getContentService(); 52775fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa try { 52785fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 52795fdc17bae46504edebe7285c3dbc7691ef3fbeb9Daisuke Miyakawa if (ContactsContract.AUTHORITY.equals(sync.authority) && 5280f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov account.type.equals(sync.accountType)) { 5281f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return sync.supportsUploading(); 5282f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5283f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5284f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } catch (RemoteException e) { 5285f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 5286f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5287f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return false; 5288f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5289f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5290f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static boolean readBooleanQueryParameter(Uri uri, String parameter, 5291f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean defaultValue) { 5292f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5293f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // Manually parse the query, which is much faster than calling uri.getQueryParameter 5294f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 5295f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 5296f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 5297f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 5298f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 5299f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = query.indexOf(parameter); 5300f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 5301f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 5302f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 53035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 53040dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov index += parameter.length(); 53050dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 53060dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return !matchQueryParameter(query, index, "=0", false) 53070dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov && !matchQueryParameter(query, index, "=false", true); 53080dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 53090dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 53100dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov private static boolean matchQueryParameter(String query, int index, String value, 53110dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov boolean ignoreCase) { 53120dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov int length = value.length(); 5313bf732767b4d4d7104e4723bda7d3b0eb0f909997Dmitri Plotnikov return query.regionMatches(ignoreCase, index, value, 0, length) 53140dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov && (query.length() == index + length || query.charAt(index + length) == '&'); 53150dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 53160dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 53170dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov /** 53180dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov * A fast re-implementation of {@link Uri#getQueryParameter} 53190dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov */ 53200dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov /* package */ static String getQueryParameter(Uri uri, String parameter) { 532149d48c0a709c1efa8593acadadd31350bfc75d9aDmitri Plotnikov String query = uri.getEncodedQuery(); 53220dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov if (query == null) { 53230dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return null; 53240dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 53250dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 53260dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov int queryLength = query.length(); 53270dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov int parameterLength = parameter.length(); 53280dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 53290dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov String value; 53300dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov int index = 0; 53310dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov while (true) { 53320dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov index = query.indexOf(parameter, index); 53330dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov if (index == -1) { 53340dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return null; 53350dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 53360dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 53370dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov index += parameterLength; 53380dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 53390dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov if (queryLength == index) { 53400dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov return null; 5341bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov } 5342bd9abbb6b03b4ec1e28ad3fa2fcba5d1eb8609eaDmitri Plotnikov 53430dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov if (query.charAt(index) == '=') { 53440dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov index++; 53450dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov break; 53460dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 53470dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } 53480dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov 53490dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov int ampIndex = query.indexOf('&', index); 53500dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov if (ampIndex == -1) { 53510dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov value = query.substring(index); 53520dce6bf7a86a78d3073327419f17395c3a2d2688Dmitri Plotnikov } else { 53539a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov value = query.substring(index, ampIndex); 53549a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 53559a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov 53569a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov return Uri.decode(value); 53579a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov } 53589a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov} 53599a6be1610fdf40c2f7f04cfe4b66fde3a35940dcDmitri Plotnikov