ContactsProvider2.java revision c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3
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 193de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.internal.content.SyncStateContentProviderHelper; 203de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport com.android.providers.contacts.ContactLookupKey.LookupKeySegment; 21b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns; 22b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns; 23b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Clauses; 24b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsColumns; 253296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkeyimport com.android.providers.contacts.ContactsDatabaseHelper.ContactsStatusUpdatesColumns; 26b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; 27b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns; 28b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns; 29b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns; 30b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType; 31b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneColumns; 32b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns; 33b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns; 34b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns; 35b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.SettingsColumns; 36b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns; 37b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 38a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Lists; 39a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Maps; 40a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport com.google.android.collect.Sets; 413de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikov 42b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 43caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikovimport android.accounts.AccountManager; 445b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanaimport android.accounts.OnAccountsUpdateListener; 45bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.Notification; 46bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.NotificationManager; 47bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.app.PendingIntent; 48c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.app.SearchManager; 49568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderOperation; 50568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.ContentProviderResult; 516ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.content.ContentResolver; 5235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 5367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentValues; 5467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.Context; 55627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.IContentService; 56bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.content.Intent; 57568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikovimport android.content.OperationApplicationException; 583d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 59627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikovimport android.content.SyncAdapterType; 6067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 61b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.content.res.AssetFileDescriptor; 624cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Taoimport android.content.res.Configuration; 631129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikovimport android.database.CharArrayBuffer; 644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 65ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.database.CursorWrapper; 66ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 6709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.MatrixCursor; 6809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.database.MatrixCursor.RowBuilder; 69a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikovimport android.database.sqlite.SQLiteConstraintException; 70b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.database.sqlite.SQLiteContentHelper; 714f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 724f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 73c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 7551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikovimport android.os.AsyncTask; 766ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshiimport android.os.Bundle; 77d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.os.MemoryFile; 78b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 790e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport android.os.SystemProperties; 80d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport android.pim.vcard.VCardComposer; 817a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawaimport android.pim.vcard.VCardConfig; 823d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 83508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 843de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract; 853de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.LiveFolders; 863de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.OpenableColumns; 873de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.SyncStateContract; 88b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 89ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikovimport android.provider.ContactsContract.ContactCounts; 903de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Contacts; 913de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Data; 925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.DisplayNameSources; 935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.FullNameStyle; 943de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Groups; 95bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikovimport android.provider.ContactsContract.Intents; 963de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.PhoneLookup; 975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikovimport android.provider.ContactsContract.PhoneticNameStyle; 9809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikovimport android.provider.ContactsContract.ProviderStatus; 993de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 100916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikovimport android.provider.ContactsContract.SearchSnippetColumns; 1013de6754a90e3682f2f52b99621d0fded060b99aeDmitri Plotnikovimport android.provider.ContactsContract.Settings; 10282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikovimport android.provider.ContactsContract.StatusUpdates; 1033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.BaseTypes; 104ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email; 105ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 1063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 1073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 1083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 109de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds.Phone; 110b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Photo; 1114097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 11267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 113a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 114a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 115c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 1164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 117d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.ByteArrayOutputStream; 118b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikovimport java.io.FileNotFoundException; 119d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.IOException; 120d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkeyimport java.io.OutputStream; 12142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.text.SimpleDateFormat; 1227e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 1235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.Collections; 12442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmannimport java.util.Date; 125b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 1260e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.HashSet; 1275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.List; 128622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkeyimport java.util.Locale; 129b5a4add17815167d20a90645779df34cdf45280dFred Quintanaimport java.util.Map; 1300e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriffimport java.util.Set; 131ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikovimport java.util.concurrent.CountDownLatch; 1324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 1344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 1354f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 1364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 1375b4b305b9698526c6e82e0e01448b0a5642dd505Fred Quintanapublic class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener { 138caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 139bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final String TAG = "ContactsProvider"; 140bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov 141bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 1424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 143619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 144619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: check for restricted flag during insert(), update(), and delete() calls 145619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 1473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 1483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1493d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 150b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov * Property key for the legacy contact import version. The need for a version 1513d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1523d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1533d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 154b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final String PROPERTY_CONTACTS_IMPORTED = "contacts_imported_v1"; 155b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov private static final int PROPERTY_CONTACTS_IMPORT_VERSION = 1; 15651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov private static final String PREF_LOCALE = "locale"; 1573d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1580e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff private static final String AGGREGATE_CONTACTS = "sync.contacts.aggregate"; 1590e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff 160a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1625e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final String TIMES_CONTACED_SORT_COLUMN = "times_contacted_sort"; 1635e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 164d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 1655e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar + TIMES_CONTACED_SORT_COLUMN + " DESC, " 1669b43551f1ce33b79141772737a262ce609bd0cebMegha Joshi + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 167d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 168d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 169d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 170d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 1716e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_CONTACTS_TABLE = 1729b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.CONTACTS + " SET " + Contacts.TIMES_CONTACTED + "=" + 1739b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + Contacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 1749b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + Contacts.TIMES_CONTACTED + " + 1) END WHERE " + Contacts._ID + "=?"; 1759b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 1766e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori /* package */ static final String UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE = 1779b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori "UPDATE " + Tables.RAW_CONTACTS + " SET " + RawContacts.TIMES_CONTACTED + "=" + 1789b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " CASE WHEN " + RawContacts.TIMES_CONTACTED + " IS NULL THEN 1 ELSE " + 1799b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori " (" + RawContacts.TIMES_CONTACTED + " + 1) END WHERE " + RawContacts.CONTACT_ID + "=?"; 1809b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori 181de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa /* package */ static final String PHONEBOOK_COLLATOR_NAME = "PHONEBOOK"; 182de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa 183d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 184d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 1855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP = 1002; 1865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_LOOKUP_ID = 1003; 1875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_DATA = 1004; 1885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_FILTER = 1005; 1895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT = 1006; 1905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_STREQUENT_FILTER = 1007; 1915870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_GROUP = 1008; 1925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private static final int CONTACTS_PHOTO = 1009; 193f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final int CONTACTS_AS_VCARD = 1010; 19442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann private static final int CONTACTS_AS_MULTI_VCARD = 1011; 1954f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1965ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 1975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 1985ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 19946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITY_ID = 2005; 2004f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2016bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 2026bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 203ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 20448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_ID = 3003; 20548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int PHONES_FILTER = 3004; 20648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS = 3005; 20748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_ID = 3006; 20848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_LOOKUP = 3007; 20948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int EMAILS_FILTER = 3008; 21048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS = 3009; 21148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov private static final int POSTALS_ID = 3010; 212a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2136bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 2146bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 215b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 216b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 217b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 21882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES = 7000; 21982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final int STATUS_UPDATES_ID = 7001; 2201f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 22131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 22231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 223eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final int SETTINGS = 9000; 224eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 225ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 226ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 227ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 228ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 22935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 230b5a4add17815167d20a90645779df34cdf45280dFred Quintana private static final int SYNCSTATE_ID = 11001; 23135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 232c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 233c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 234c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2351b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS = 14000; 2361b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_WITH_PHONES = 14001; 2371b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_FAVORITES = 14002; 2381b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final int LIVE_FOLDERS_CONTACTS_GROUP_NAME = 14003; 2391b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 24046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final int RAW_CONTACT_ENTITIES = 15001; 24146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 24209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private static final int PROVIDER_STATUS = 16001; 24309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 244dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID = 245dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 246dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME 247dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 248dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE 249dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + RawContactsColumns.CONCRETE_ACCOUNT_TYPE 250dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND " + Groups.FAVORITES + " != 0"; 251dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 252dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID = 253dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana RawContactsColumns.CONCRETE_ID + "=? AND " 254dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" 255dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_NAME + " AND " 256dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 257dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + " AND " 258dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + Groups.AUTO_ADD + " != 0"; 259dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 260dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String[] PROJECTION_GROUP_ID 261dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana = new String[]{Tables.GROUPS + "." + Groups._ID}; 262dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 263dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_GROUPMEMBERSHIP_DATA = DataColumns.MIMETYPE_ID + "=? " 264dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.GROUP_ROW_ID + "=? " 265dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "AND " + GroupMembership.RAW_CONTACT_ID + "=?"; 266dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 267dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_STARRED_FROM_RAW_CONTACTS = 268dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana "SELECT " + RawContacts.STARRED 269dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?"; 270dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 271d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 272f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov public static final String TABLE = "data " 273f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 274f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 27567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 27667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 2776cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 2783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 279f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov ContactsColumns.CONCRETE_ID 280ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 281ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 282d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 28367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 284d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 285ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2861f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 28714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataDeleteQuery { 28867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 29088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] CONCRETE_COLUMNS = new String[] { 2913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 2923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID, 2943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 295f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 29688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov }; 29788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov 29888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov public static final String[] COLUMNS = new String[] { 29988e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data._ID, 30088e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov MimetypesColumns.MIMETYPE, 30188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.RAW_CONTACT_ID, 30288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov Data.IS_PRIMARY, 303f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov Data.DATA1, 3043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 3053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 30614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public static final int _ID = 0; 3073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 1; 3085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 2; 3093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 3; 310f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public static final int DATA1 = 4; 3113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 3123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 31314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov private interface DataUpdateQuery { 314321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana String[] COLUMNS = { Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE }; 31520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 31620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int _ID = 0; 317321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int RAW_CONTACT_ID = 1; 318321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int MIMETYPE = 2; 31920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 32020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 321f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 32219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka private interface RawContactsQuery { 32319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String TABLE = Tables.RAW_CONTACTS; 32419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 32519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka String[] COLUMNS = new String[] { 326ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.DELETED, 327ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 328ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov RawContacts.ACCOUNT_NAME, 32919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka }; 33019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 33119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int DELETED = 0; 332ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_TYPE = 1; 333ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int ACCOUNT_NAME = 2; 33419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 33519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka 336c76cdd0723b99f478c9ba5329d14a971cd8dfb3dCostin Manolache public static final String DEFAULT_ACCOUNT_TYPE = "com.google"; 337df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana public static final String FEATURE_LEGACY_HOSTED_OR_GOOGLE = "legacy_hosted_or_google"; 338caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 33971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov /** Sql where statement for filtering on groups. */ 34071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov private static final String CONTACTS_IN_GROUP_SELECT = 34171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov Contacts._ID + " IN " 34271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + RawContacts.CONTACT_ID 34371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.RAW_CONTACTS 34471e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + " IN " 34571e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + DataColumns.CONCRETE_RAW_CONTACT_ID 34671e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.DATA_JOIN_MIMETYPES 34771e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE 34871e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "' AND " + GroupMembership.GROUP_ROW_ID + "=" 34971e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + "(SELECT " + Tables.GROUPS + "." + Groups._ID 35071e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " FROM " + Tables.GROUPS 35171e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov + " WHERE " + Groups.TITLE + "=?)))"; 35271e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov 353a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating DIRTY flag on multiple raw contacts */ 354a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_DIRTY_SQL = 355a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 356a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.DIRTY + "=1" + 357a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 358a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 359a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** Sql for updating VERSION on multiple raw contacts */ 360a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private static final String UPDATE_RAW_CONTACT_SET_VERSION_SQL = 361a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 362a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + 363a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + RawContacts._ID + " IN ("; 364a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 365916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Name lookup types used for contact filtering */ 366916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final String CONTACT_LOOKUP_NAME_TYPES = 367916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_COLLATION_KEY + "," + 368916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME + "," + 369916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NICKNAME + "," + 370916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov NameLookupType.NAME_SHORTHAND + "," + 371f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee NameLookupType.ORGANIZATION + "," + 372f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee NameLookupType.NAME_CONSONANTS; 373916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 374916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 375038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana /** Contains just BaseColumns._COUNT */ 376038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana private static final HashMap<String, String> sCountProjectionMap; 377e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov /** Contains just the contacts columns */ 3784f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 379916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** Contains just the contacts columns */ 380916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private static final HashMap<String, String> sContactsProjectionWithSnippetMap; 381916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 3825e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar /** Used for pushing starred contacts to the top of a times contacted list **/ 3835e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final HashMap<String, String> sStrequentStarredProjectionMap; 3845e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private static final HashMap<String, String> sStrequentFrequentProjectionMap; 385f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey /** Contains just the contacts vCard columns */ 386f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey private static final HashMap<String, String> sContactsVCardProjectionMap; 387ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov /** Contains just the raw contacts columns */ 388d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 38946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana /** Contains the columns from the raw contacts entity view*/ 39046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private static final HashMap<String, String> sRawContactsEntityProjectionMap; 3914a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** Contains columns from the data view */ 3924a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private static final HashMap<String, String> sDataProjectionMap; 3935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** Contains columns from the data view */ 3945e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private static final HashMap<String, String> sDistinctDataProjectionMap; 3959261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 396e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov private static final HashMap<String, String> sPhoneLookupProjectionMap; 397ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 398ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 399ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 400ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 401373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 402b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 403eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey /** Contains the agg_exceptions columns */ 404eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey private static final HashMap<String, String> sSettingsProjectionMap; 40582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Contains StatusUpdates columns */ 40682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private static final HashMap<String, String> sStatusUpdatesProjectionMap; 4071b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov /** Contains Live Folders columns */ 4081b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov private static final HashMap<String, String> sLiveFoldersProjectionMap; 4097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 4109705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // where clause to update the status_updates table 4119705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private static final String WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE = 4129705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdatesColumns.DATA_ID + " IN (SELECT Distinct " + StatusUpdates.DATA_ID + 4139705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " FROM " + Tables.STATUS_UPDATES + " LEFT OUTER JOIN " + Tables.PRESENCE + 4149705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori " ON " + StatusUpdatesColumns.DATA_ID + " = " + StatusUpdates.DATA_ID + " WHERE "; 4159705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 4162526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private static final String[] EMPTY_STRING_ARRAY = new String[0]; 4172526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 418bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 419bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Notification ID for failure to import contacts. 420bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 421bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private static final int LEGACY_IMPORT_FAILED_NOTIFICATION = 1; 42251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 423c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 424c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 4253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 426c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 4273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 42825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov private SQLiteStatement mRawContactDisplayNameUpdate; 42982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov /** Precompiled sql statement for updating an aggregated status update */ 430a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mLastStatusUpdate; 431f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupInsert; 432f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private SQLiteStatement mNameLookupDelete; 433a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateAutoTimestamp; 434a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateInsert; 435a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateReplace; 4360a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private SQLiteStatement mStatusAttributionUpdate; 437a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov private SQLiteStatement mStatusUpdateDelete; 438f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov private SQLiteStatement mResetNameVerifiedForOtherRawContacts; 439a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 440f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdEmail; 441f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private long mMimeTypeIdIm; 4421129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdStructuredName; 4431129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdOrganization; 4441129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdNickname; 4451129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private long mMimeTypeIdPhone; 446f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov private StringBuilder mSb = new StringBuilder(); 4471129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs1 = new String[1]; 4481129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private String[] mSelectionArgs2 = new String[2]; 4492526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov private ArrayList<String> mSelectionArgs = Lists.newArrayList(); 4502526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov 451f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private Account mAccount; 452f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 4534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 4544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 455a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 456d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 457d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 458d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 4593653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 4603653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 4612d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", 4622d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov AGGREGATION_SUGGESTIONS); 4633653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_PHOTO); 464c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter", CONTACTS_FILTER); 4655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER); 4665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP); 4675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID); 468f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_vcard/*", CONTACTS_AS_VCARD); 46942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann matcher.addURI(ContactsContract.AUTHORITY, "contacts/as_multi_vcard/*", 47042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann CONTACTS_AS_MULTI_VCARD); 4715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/", CONTACTS_STREQUENT); 472ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/strequent/filter/*", 473ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov CONTACTS_STREQUENT_FILTER); 4745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/group/*", CONTACTS_GROUP); 4753653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 4765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 4775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 4785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 47946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/entity", RAW_CONTACT_ENTITY_ID); 48046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 48146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana matcher.addURI(ContactsContract.AUTHORITY, "raw_contact_entities", RAW_CONTACT_ENTITIES); 482b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 4834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 4844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 485ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 48648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); 4875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER); 488ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 4894a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails", EMAILS); 49048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/#", EMAILS_ID); 4915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/lookup/*", EMAILS_LOOKUP); 4925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter", EMAILS_FILTER); 4934a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/emails/filter/*", EMAILS_FILTER); 494ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 49548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "data/postals/#", POSTALS_ID); 4961f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 497ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 498ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 499ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 500ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 50135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 502b5a4add17815167d20a90645779df34cdf45280dFred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH + "/#", 503b5a4add17815167d20a90645779df34cdf45280dFred Quintana SYNCSTATE_ID); 50435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 505a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 506b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 507b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 508b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 509b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 5104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 511eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "settings", SETTINGS); 512eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 51382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates", STATUS_UPDATES); 51482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "status_updates/#", STATUS_UPDATES_ID); 5151f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 516c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 517c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 518c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 519c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 5202d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", 521c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 522c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 5231b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts", 5241b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS); 5251b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts/*", 5261b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_GROUP_NAME); 5271b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/contacts_with_phones", 5281b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_WITH_PHONES); 5291b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "live_folders/favorites", 5301b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov LIVE_FOLDERS_CONTACTS_FAVORITES); 53109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 53209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "provider_status", PROVIDER_STATUS); 53319a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov } 53419a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 53519a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov static { 536038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap = new HashMap<String, String>(); 537038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*)"); 538e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 5394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap = new HashMap<String, String>(); 5404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts._ID, Contacts._ID); 5415dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME_PRIMARY); 5425dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME_ALTERNATIVE, 5435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE); 5445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.DISPLAY_NAME_SOURCE, Contacts.DISPLAY_NAME_SOURCE); 5455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHONETIC_NAME, Contacts.PHONETIC_NAME); 5465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHONETIC_NAME_STYLE, Contacts.PHONETIC_NAME_STYLE); 5475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SORT_KEY_PRIMARY, Contacts.SORT_KEY_PRIMARY); 5485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SORT_KEY_ALTERNATIVE, Contacts.SORT_KEY_ALTERNATIVE); 5494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 5504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 5514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 5524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 5534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 5544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 555f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov sContactsProjectionMap.put(Contacts.HAS_PHONE_NUMBER, Contacts.HAS_PHONE_NUMBER); 5564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sContactsProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 5575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sContactsProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 55880d7871ca31d604cbfd857661d5300bb090076dbDaniel Lehmann sContactsProjectionMap.put(Contacts.NAME_RAW_CONTACT_ID, Contacts.NAME_RAW_CONTACT_ID); 559f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 5603296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 5613296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_PRESENCE, 5623296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 5633296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS, 5643296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 5653296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 5663296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 5673296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 5683296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 5693296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_LABEL, 5703296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 5713296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sContactsProjectionMap, Contacts.CONTACT_STATUS_ICON, 5723296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 5733296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 574916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sContactsProjectionWithSnippetMap = new HashMap<String, String>(); 575916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sContactsProjectionWithSnippetMap.putAll(sContactsProjectionMap); 576916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_MIMETYPE, 577916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov SearchSnippetColumns.SNIPPET_MIMETYPE); 578916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA_ID, 579916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA_ID); 5809c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA1, 5819c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA1); 5829c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA2, 5839c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA2); 5849c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA3, 5859c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA3); 5869c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sContactsProjectionWithSnippetMap.put(SearchSnippetColumns.SNIPPET_DATA4, 5879c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov SearchSnippetColumns.SNIPPET_DATA4); 588916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5895e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentStarredProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 5905e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentStarredProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 5915e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar Long.MAX_VALUE + " AS " + TIMES_CONTACED_SORT_COLUMN); 5925e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 5935e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentFrequentProjectionMap = new HashMap<String, String>(sContactsProjectionMap); 5945e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar sStrequentFrequentProjectionMap.put(TIMES_CONTACED_SORT_COLUMN, 5955e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar Contacts.TIMES_CONTACTED + " AS " + TIMES_CONTACED_SORT_COLUMN); 5965e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 597f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap = Maps.newHashMap(); 598f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.DISPLAY_NAME, Contacts.DISPLAY_NAME 599d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey + " || '.vcf' AS " + OpenableColumns.DISPLAY_NAME); 600ba355248c255551bc65d8023b968513cbe9bcdf3Jeff Sharkey sContactsVCardProjectionMap.put(OpenableColumns.SIZE, "NULL AS " + OpenableColumns.SIZE); 6014a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 6024a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap = new HashMap<String, String>(); 6034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts._ID, RawContacts._ID); 6044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 6054a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 6064a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 6074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 6084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 6094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 6104a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DELETED, RawContacts.DELETED); 6115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DISPLAY_NAME_PRIMARY, 6125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_PRIMARY); 6135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DISPLAY_NAME_ALTERNATIVE, 6145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_ALTERNATIVE); 6155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.DISPLAY_NAME_SOURCE, 6165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_SOURCE); 6175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.PHONETIC_NAME, 6185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME); 6195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.PHONETIC_NAME_STYLE, 6205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME_STYLE); 621f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.NAME_VERIFIED, 622f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov RawContacts.NAME_VERIFIED); 6235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SORT_KEY_PRIMARY, 6245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_PRIMARY); 6255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SORT_KEY_ALTERNATIVE, 6265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_ALTERNATIVE); 6274a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.TIMES_CONTACTED, RawContacts.TIMES_CONTACTED); 6284a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.LAST_TIME_CONTACTED, 6294a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov RawContacts.LAST_TIME_CONTACTED); 6304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.CUSTOM_RINGTONE, RawContacts.CUSTOM_RINGTONE); 6314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SEND_TO_VOICEMAIL, RawContacts.SEND_TO_VOICEMAIL); 6324a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.STARRED, RawContacts.STARRED); 6334a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE); 6344a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC1, RawContacts.SYNC1); 6354a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC2, RawContacts.SYNC2); 6364a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC3, RawContacts.SYNC3); 6374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sRawContactsProjectionMap.put(RawContacts.SYNC4, RawContacts.SYNC4); 6382815f58f72f109790585931f601a63ddc02536a5Evan Millar 6394a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap = new HashMap<String, String>(); 6404a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data._ID, Data._ID); 6414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 6424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 6434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 6444a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 6454a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 6464a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 6474a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA1, Data.DATA1); 6484a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA2, Data.DATA2); 6494a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA3, Data.DATA3); 6504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA4, Data.DATA4); 6514a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA5, Data.DATA5); 6524a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA6, Data.DATA6); 6534a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA7, Data.DATA7); 6544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA8, Data.DATA8); 6554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA9, Data.DATA9); 6564a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA10, Data.DATA10); 6574a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA11, Data.DATA11); 6584a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA12, Data.DATA12); 6594a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA13, Data.DATA13); 6604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA14, Data.DATA14); 6614a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.DATA15, Data.DATA15); 6624a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 6634a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 6644a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 6654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 66682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sDataProjectionMap.put(Data.CONTACT_ID, Data.CONTACT_ID); 6674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 6684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 6694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 6704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.VERSION, RawContacts.VERSION); 6714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(RawContacts.DIRTY, RawContacts.DIRTY); 672f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov sDataProjectionMap.put(RawContacts.NAME_VERIFIED, RawContacts.NAME_VERIFIED); 67356d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 6744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 6755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME_ALTERNATIVE, 6765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE); 6775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.DISPLAY_NAME_SOURCE, Contacts.DISPLAY_NAME_SOURCE); 6785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHONETIC_NAME, Contacts.PHONETIC_NAME); 6795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHONETIC_NAME_STYLE, Contacts.PHONETIC_NAME_STYLE); 6805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.SORT_KEY_PRIMARY, Contacts.SORT_KEY_PRIMARY); 6815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDataProjectionMap.put(Contacts.SORT_KEY_ALTERNATIVE, Contacts.SORT_KEY_ALTERNATIVE); 6824a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 6834a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 6844a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 6854a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 6864a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 6874a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 688a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 689afbf2a3343d0f8e7ae7cbfbbec60004ed37caf3fDaniel Lehmann sDataProjectionMap.put(Contacts.NAME_RAW_CONTACT_ID, Contacts.NAME_RAW_CONTACT_ID); 6904a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov sDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 691a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 69246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana HashMap<String, String> columns; 69346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns = new HashMap<String, String>(); 69446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts._ID, RawContacts._ID); 69546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 69646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_NAME); 69746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_TYPE); 69846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SOURCE_ID, RawContacts.SOURCE_ID); 69946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.VERSION, RawContacts.VERSION); 70046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DIRTY, RawContacts.DIRTY); 70146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.DELETED, RawContacts.DELETED); 702bf6a7e4dece49ba4e7cda17f7ed9250aeb82f731Jeff Sharkey columns.put(RawContacts.IS_RESTRICTED, RawContacts.IS_RESTRICTED); 70346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC1, RawContacts.SYNC1); 70446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC2, RawContacts.SYNC2); 70546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC3, RawContacts.SYNC3); 70646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.SYNC4, RawContacts.SYNC4); 707f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov columns.put(RawContacts.NAME_VERIFIED, RawContacts.NAME_VERIFIED); 70846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 70946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.MIMETYPE, Data.MIMETYPE); 71046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA1, Data.DATA1); 71146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA2, Data.DATA2); 71246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA3, Data.DATA3); 71346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA4, Data.DATA4); 71446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA5, Data.DATA5); 71546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA6, Data.DATA6); 71646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA7, Data.DATA7); 71746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA8, Data.DATA8); 71846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA9, Data.DATA9); 71946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA10, Data.DATA10); 72046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA11, Data.DATA11); 72146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA12, Data.DATA12); 72246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA13, Data.DATA13); 72346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA14, Data.DATA14); 72446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA15, Data.DATA15); 72546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC1, Data.SYNC1); 72646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC2, Data.SYNC2); 72746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC3, Data.SYNC3); 72846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.SYNC4, Data.SYNC4); 72946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(RawContacts.Entity.DATA_ID, RawContacts.Entity.DATA_ID); 73046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.STARRED, Data.STARRED); 73146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.DATA_VERSION, Data.DATA_VERSION); 73246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 73346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 73446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana columns.put(GroupMembership.GROUP_SOURCE_ID, GroupMembership.GROUP_SOURCE_ID); 73546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana sRawContactsEntityProjectionMap = columns; 73646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 7373296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 7383296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_PRESENCE, 7393296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 7403296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS, 7413296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 7423296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 7433296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7443296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 7453296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7463296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 7473296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7483296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 7493296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 7503296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 7513296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 7523296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.PRESENCE, 7533296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 7543296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS, 7553296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 7563296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_TIMESTAMP, 7573296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 7583296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_RES_PACKAGE, 7593296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 7603296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_LABEL, 7613296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 7623296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDataProjectionMap, Data.STATUS_ICON, 7633296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 7643296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 7655e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov // Projection map for data grouped by contact (not raw contact) and some data field(s) 7665e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap = new HashMap<String, String>(); 7675e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data._ID, 7685e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov "MIN(" + Data._ID + ") AS " + Data._ID); 7695e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA_VERSION, Data.DATA_VERSION); 7705e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 7715e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 7725e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.RES_PACKAGE, Data.RES_PACKAGE); 7735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.MIMETYPE, Data.MIMETYPE); 7745e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA1, Data.DATA1); 7755e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA2, Data.DATA2); 7765e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA3, Data.DATA3); 7775e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA4, Data.DATA4); 7785e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA5, Data.DATA5); 7795e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA6, Data.DATA6); 7805e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA7, Data.DATA7); 7815e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA8, Data.DATA8); 7825e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA9, Data.DATA9); 7835e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA10, Data.DATA10); 7845e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA11, Data.DATA11); 7855e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA12, Data.DATA12); 7865e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA13, Data.DATA13); 7875e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA14, Data.DATA14); 7885e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.DATA15, Data.DATA15); 7895e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC1, Data.SYNC1); 7905e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC2, Data.SYNC2); 7915e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC3, Data.SYNC3); 7925e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Data.SYNC4, Data.SYNC4); 7935e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 7948f1631f8a610e7278526916ce73ac1e422a5c9b8Jeff Sharkey sDistinctDataProjectionMap.put(Contacts.LOOKUP_KEY, Contacts.LOOKUP_KEY); 7955e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME); 7965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME_ALTERNATIVE, 7975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.DISPLAY_NAME_ALTERNATIVE); 7985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.DISPLAY_NAME_SOURCE, Contacts.DISPLAY_NAME_SOURCE); 7995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHONETIC_NAME, Contacts.PHONETIC_NAME); 8005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHONETIC_NAME_STYLE, Contacts.PHONETIC_NAME_STYLE); 8015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SORT_KEY_PRIMARY, Contacts.SORT_KEY_PRIMARY); 8025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SORT_KEY_ALTERNATIVE, 8035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov Contacts.SORT_KEY_ALTERNATIVE); 8045e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.CUSTOM_RINGTONE, Contacts.CUSTOM_RINGTONE); 8055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.SEND_TO_VOICEMAIL, Contacts.SEND_TO_VOICEMAIL); 8065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.LAST_TIME_CONTACTED, Contacts.LAST_TIME_CONTACTED); 8075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.TIMES_CONTACTED, Contacts.TIMES_CONTACTED); 8085e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.STARRED, Contacts.STARRED); 8095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 810a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sDistinctDataProjectionMap.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 8115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sDistinctDataProjectionMap.put(GroupMembership.GROUP_SOURCE_ID, 8125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov GroupMembership.GROUP_SOURCE_ID); 8135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 8143296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Contacts-level statuses 8153296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_PRESENCE, 8163296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.AGGREGATED_PRESENCE + "." + StatusUpdates.PRESENCE); 8173296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS, 8183296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS); 8193296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_TIMESTAMP, 8203296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 8213296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_RES_PACKAGE, 8223296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 8233296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_LABEL, 8243296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_LABEL); 8253296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Contacts.CONTACT_STATUS_ICON, 8263296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey ContactsStatusUpdatesColumns.CONCRETE_STATUS_ICON); 8273296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 8283296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Handle projections for Data-level statuses 8293296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.PRESENCE, 8303296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Tables.PRESENCE + "." + StatusUpdates.PRESENCE); 8313296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS, 8323296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS); 8333296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_TIMESTAMP, 8343296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_TIMESTAMP); 8353296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_RES_PACKAGE, 8363296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_RES_PACKAGE); 8373296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_LABEL, 8383296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_LABEL); 8393296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey addProjection(sDistinctDataProjectionMap, Data.STATUS_ICON, 8403296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey StatusUpdatesColumns.CONCRETE_STATUS_ICON); 8413296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 842e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap = new HashMap<String, String>(); 843e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup._ID, 844fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts._ID 845fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup._ID); 84656d2bd40ebb238c2990bc239f68c7e61c7d5b02cEvan Millar sPhoneLookupProjectionMap.put(PhoneLookup.LOOKUP_KEY, 847fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.LOOKUP_KEY 848fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.LOOKUP_KEY); 849e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.DISPLAY_NAME, 850fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.DISPLAY_NAME 851fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.DISPLAY_NAME); 852e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LAST_TIME_CONTACTED, 853fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.LAST_TIME_CONTACTED 854e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.LAST_TIME_CONTACTED); 855e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TIMES_CONTACTED, 856fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.TIMES_CONTACTED 857fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.TIMES_CONTACTED); 858e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.STARRED, 859fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.STARRED 860fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.STARRED); 861e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.IN_VISIBLE_GROUP, 862fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.IN_VISIBLE_GROUP 863fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.IN_VISIBLE_GROUP); 864e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.PHOTO_ID, 865fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.PHOTO_ID 866fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.PHOTO_ID); 867e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.CUSTOM_RINGTONE, 868fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.CUSTOM_RINGTONE 869fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.CUSTOM_RINGTONE); 870e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.HAS_PHONE_NUMBER, 871fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.HAS_PHONE_NUMBER 872fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov + " AS " + PhoneLookup.HAS_PHONE_NUMBER); 873e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.SEND_TO_VOICEMAIL, 874fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov "contacts_view." + Contacts.SEND_TO_VOICEMAIL 875e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov + " AS " + PhoneLookup.SEND_TO_VOICEMAIL); 876e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.NUMBER, 877e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.NUMBER + " AS " + PhoneLookup.NUMBER); 878e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.TYPE, 879e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.TYPE + " AS " + PhoneLookup.TYPE); 880e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sPhoneLookupProjectionMap.put(PhoneLookup.LABEL, 881e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov Phone.LABEL + " AS " + PhoneLookup.LABEL); 8829261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 883ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 884ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 88589c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups._ID, Groups._ID); 886035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 887035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 8889261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 8899261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.DIRTY, Groups.DIRTY); 8909261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.VERSION, Groups.VERSION); 89189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.RES_PACKAGE, Groups.RES_PACKAGE); 892ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 89367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 894ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 8953cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYSTEM_ID, Groups.SYSTEM_ID); 89694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana columns.put(Groups.DELETED, Groups.DELETED); 8973cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.NOTES, Groups.NOTES); 89838446bf47c5ee2080df69f5fc8a33ad2fa3e61b5Jeff Sharkey columns.put(Groups.SHOULD_SYNC, Groups.SHOULD_SYNC); 899dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana columns.put(Groups.FAVORITES, Groups.FAVORITES); 900dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana columns.put(Groups.AUTO_ADD, Groups.AUTO_ADD); 90189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC1, Groups.SYNC1); 90289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC2, Groups.SYNC2); 90389c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC3, Groups.SYNC3); 90489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov columns.put(Groups.SYNC4, Groups.SYNC4); 905ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 906ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 9076cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts and groups projection map 908ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 909ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 910d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 911d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 912ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 913ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 914ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 915d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 916d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 917ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 918f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov + " AND " + Contacts.HAS_PHONE_NUMBER + ") AS " + Groups.SUMMARY_WITH_PHONES); 919ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 920ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 921b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 922b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 923b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 924b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 9250c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID1, AggregationExceptions.RAW_CONTACT_ID1); 9260c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID2, AggregationExceptions.RAW_CONTACT_ID2); 927b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 928b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 929eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey // Settings projection map 930eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns = new HashMap<String, String>(); 931eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_NAME, Settings.ACCOUNT_NAME); 932eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.ACCOUNT_TYPE, Settings.ACCOUNT_TYPE); 933eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.UNGROUPED_VISIBLE, Settings.UNGROUPED_VISIBLE); 934eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey columns.put(Settings.SHOULD_SYNC, Settings.SHOULD_SYNC); 935341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey columns.put(Settings.ANY_UNSYNCED, "(CASE WHEN MIN(" + Settings.SHOULD_SYNC 936341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + ",(SELECT (CASE WHEN MIN(" + Groups.SHOULD_SYNC + ") IS NULL THEN 1 ELSE MIN(" 937341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Groups.SHOULD_SYNC + ") END) FROM " + Tables.GROUPS + " WHERE " 938fc4e892529eccdfa42121f0304ec7d0dbb42d6c9Dmitri Plotnikov + GroupsColumns.CONCRETE_ACCOUNT_NAME + "=" + SettingsColumns.CONCRETE_ACCOUNT_NAME 939341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + " AND " + GroupsColumns.CONCRETE_ACCOUNT_TYPE + "=" 940341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + SettingsColumns.CONCRETE_ACCOUNT_TYPE + "))=0 THEN 1 ELSE 0 END) AS " 941341e4621f2ee7614c66bc25dd3da70eaaa866b46Jeff Sharkey + Settings.ANY_UNSYNCED); 94268936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_COUNT, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 94368936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " GROUP BY " 94468936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID + " HAVING " + Clauses.HAVING_NO_GROUPS 94568936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + ")) AS " + Settings.UNGROUPED_COUNT); 94668936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey columns.put(Settings.UNGROUPED_WITH_PHONES, "(SELECT COUNT(*) FROM (SELECT 1 FROM " 947e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey + Tables.SETTINGS_JOIN_RAW_CONTACTS_DATA_MIMETYPES_CONTACTS + " WHERE " 94868936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Contacts.HAS_PHONE_NUMBER + " GROUP BY " + Clauses.GROUP_BY_ACCOUNT_CONTACT_ID 94968936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + " HAVING " + Clauses.HAVING_NO_GROUPS + ")) AS " 95068936cefd4caa779169ea00ffd1adc399e634c9bJeff Sharkey + Settings.UNGROUPED_WITH_PHONES); 951eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey sSettingsProjectionMap = columns; 952eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 953373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns = new HashMap<String, String>(); 9544dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov columns.put(PresenceColumns.RAW_CONTACT_ID, PresenceColumns.RAW_CONTACT_ID); 9550a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.DATA_ID, 9560a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov DataColumns.CONCRETE_ID + " AS " + StatusUpdates.DATA_ID); 95782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_ACCOUNT, StatusUpdates.IM_ACCOUNT); 95882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.IM_HANDLE, StatusUpdates.IM_HANDLE); 95982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PROTOCOL, StatusUpdates.PROTOCOL); 96070c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 96170c314fb9b2ef3d47340b93816d46200aba9f5ecDmitri Plotnikov // properly enforce uniqueness of null values 96282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.CUSTOM_PROTOCOL, "(CASE WHEN " + StatusUpdates.CUSTOM_PROTOCOL 96382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + "='' THEN NULL ELSE " + StatusUpdates.CUSTOM_PROTOCOL + " END) AS " 96482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + StatusUpdates.CUSTOM_PROTOCOL); 96582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov columns.put(StatusUpdates.PRESENCE, StatusUpdates.PRESENCE); 9660a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS, StatusUpdates.STATUS); 9670a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_TIMESTAMP, StatusUpdates.STATUS_TIMESTAMP); 9680a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_RES_PACKAGE, StatusUpdates.STATUS_RES_PACKAGE); 9690a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_ICON, StatusUpdates.STATUS_ICON); 9700a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov columns.put(StatusUpdates.STATUS_LABEL, StatusUpdates.STATUS_LABEL); 97182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sStatusUpdatesProjectionMap = columns; 97219a0962e62c13a5e5f8e5b4eed5e30d3477894b4Dmitri Plotnikov 9731b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Live folder projection 9741b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap = new HashMap<String, String>(); 9751b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders._ID, 9761b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts._ID + " AS " + LiveFolders._ID); 9771b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov sLiveFoldersProjectionMap.put(LiveFolders.NAME, 9781b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov Contacts.DISPLAY_NAME + " AS " + LiveFolders.NAME); 9791b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // TODO: Put contact photo back when we have a way to display a default icon 9801b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // for contacts without a photo 9811b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // sLiveFoldersProjectionMap.put(LiveFolders.ICON_BITMAP, 9821b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov // Photos.DATA + " AS " + LiveFolders.ICON_BITMAP); 9834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 9844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 9853296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey private static void addProjection(HashMap<String, String> map, String toField, String fromField) { 9863296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey map.put(toField, fromField + " AS " + toField); 9873296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 9883296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 9893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 9903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 9913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 9923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 9933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 995653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long mMimetypeId; 9963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9971129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov @SuppressWarnings("all") 9983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 9993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 1000a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 1001a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka // To ensure the data column position. This is dead code if properly configured. 1002a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (StructuredName.DISPLAY_NAME != Data.DATA1 || Nickname.NAME != Data.DATA1 1003a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Organization.COMPANY != Data.DATA1 || Phone.NUMBER != Data.DATA1 1004a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka || Email.DATA != Data.DATA1) { 1005a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka throw new AssertionError("Some of ContactsContract.CommonDataKinds class primary" 1006a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + " data is not in DATA1 column"); 1007a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 10083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1010653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov protected long getMimeTypeId() { 1011653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (mMimetypeId == 0) { 1012b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mMimetypeId = mDbHelper.getMimeTypeId(mMimetype); 1013653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1014653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return mMimetypeId; 1015653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1016653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 10173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 10183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 10193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 10205ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1021e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 1022e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1023e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 1024e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 1025653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 1026e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1027e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1028e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 10293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 10323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 10333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 1034813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov * 1035813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov * @return true if update changed something 10363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 1037813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1038f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 103914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 104014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1041653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1042653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.containsKey(Data.IS_SUPER_PRIMARY)) { 1043653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov long mimeTypeId = getMimeTypeId(); 1044653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsSuperPrimary(rawContactId, dataId, mimeTypeId); 1045653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, mimeTypeId); 1046653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1047653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 1048653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_SUPER_PRIMARY); 1049653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 1050653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else if (values.containsKey(Data.IS_PRIMARY)) { 1051653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setIsPrimary(rawContactId, dataId, getMimeTypeId()); 1052653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1053653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 1054653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(Data.IS_PRIMARY); 1055653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1056653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1057653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() > 0) { 10584da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 10594da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mDb.update(Tables.DATA, values, Data._ID + " =?", mSelectionArgs1); 1060653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1061653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1062f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 1063653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov setRawContactDirty(rawContactId); 1064653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1065813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1066813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 10673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 107014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 107114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 107214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov boolean primary = c.getInt(DataDeleteQuery.IS_PRIMARY) != 0; 10734da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 10744da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=?", mSelectionArgs1); 10754da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 10764da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov db.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=?", mSelectionArgs1); 10773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 10785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 10793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 10813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10835ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 10844da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov long mimeTypeId = getMimeTypeId(); 1085e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 1086e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 10874da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 10884da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = db.query(DataDeleteQuery.TABLE, 10894da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov DataDeleteQuery.CONCRETE_COLUMNS, 10904da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Data.RAW_CONTACT_ID + "=?" + 10914da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov " AND " + DataColumns.MIMETYPE_ID + "=" + mimeTypeId, 10924da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null, null, null); 10933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 1094e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 109514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 1096f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov int type = c.getInt(DataDeleteQuery.DATA1); 1097e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 1098e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 1099e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 1100e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 11013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 11033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 11043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11054da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (primaryId != -1) { 11064da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov setIsPrimary(rawContactId, primaryId, mimeTypeId); 11074da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 1108e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1109e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1110e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 1111e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 1112e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 1113e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 1114e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1115e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 11163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 111825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov protected void fixRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 1119285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1120d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov updateRawContactDisplayName(db, rawContactId); 1121fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(db, rawContactId); 1122285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 11233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 1124a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1125622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1126622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Return set of values, using current values at given {@link Data#_ID} 1127813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov * as baseline, but augmented with any updates. Returns null if there is 1128813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov * no change. 1129622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1130622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public ContentValues getAugmentedValues(SQLiteDatabase db, long dataId, 1131622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey ContentValues update) { 1132813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov boolean changing = false; 1133622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues values = new ContentValues(); 11344da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 11354da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov final Cursor cursor = db.query(Tables.DATA, null, Data._ID + "=?", 11364da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null, null, null); 1137622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey try { 1138622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (cursor.moveToFirst()) { 1139622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (int i = 0; i < cursor.getColumnCount(); i++) { 1140622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String key = cursor.getColumnName(i); 1141813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov final String value = cursor.getString(i); 1142813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!changing && update.containsKey(key)) { 1143813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov Object newValue = update.get(key); 1144813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String newString = newValue == null ? null : newValue.toString(); 1145813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov changing |= !TextUtils.equals(newString, value); 1146813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1147813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov values.put(key, value); 1148622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1149622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1150622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } finally { 1151622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey cursor.close(); 1152622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1153813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!changing) { 1154813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return null; 1155813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1156813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1157622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey values.putAll(update); 1158622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return values; 1159622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 11603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 11633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 11653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 11663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 1170622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final NameSplitter mSplitter; 11713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1172622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredNameRowHandler(NameSplitter splitter) { 11733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 1174622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 11753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 11785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1179622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(values, values); 118014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 118114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 118214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1183f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name = values.getAsString(StructuredName.DISPLAY_NAME); 1184d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov Integer fullNameStyle = values.getAsInteger(StructuredName.FULL_NAME_STYLE); 1185d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name, 118651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov fullNameStyle != null 118751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov ? mNameSplitter.getAdjustedFullNameStyle(fullNameStyle) 118851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov : FullNameStyle.UNDEFINED); 118948786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov insertNameLookupForPhoneticName(rawContactId, dataId, values); 119025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1191813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 119214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 119314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 119414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 119514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 1196813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1197f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1198622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1199622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1200cabac02a2416b495e030654accffcbb5ae526678Dmitri Plotnikov 1201622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1202813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (augmented == null) { // No change 1203813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1204813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1205813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1206622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredNameComponents(augmented, values); 120714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1208f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 12097ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov if (values.containsKey(StructuredName.DISPLAY_NAME) || 12107ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov values.containsKey(StructuredName.PHONETIC_FAMILY_NAME) || 12117ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov values.containsKey(StructuredName.PHONETIC_MIDDLE_NAME) || 12127ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov values.containsKey(StructuredName.PHONETIC_GIVEN_NAME)) { 12137ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov augmented.putAll(values); 12147ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov String name = augmented.getAsString(StructuredName.DISPLAY_NAME); 1215f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 12167ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov Integer fullNameStyle = augmented.getAsInteger(StructuredName.FULL_NAME_STYLE); 1217d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov insertNameLookupForStructuredName(rawContactId, dataId, name, 121851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov fullNameStyle != null 121951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov ? mNameSplitter.getAdjustedFullNameStyle(fullNameStyle) 122051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov : FullNameStyle.UNDEFINED); 12217ceafd016eb07d2de808d18cd5a9463efaee781dDmitri Plotnikov insertNameLookupForPhoneticName(rawContactId, dataId, augmented); 122214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 122325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1224813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1225813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 122614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 122714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 122814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 122914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 123014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 123114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 123214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 123314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 123414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1235f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 123625abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1237813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 123814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 12393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 12403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 12413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 1242622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 12433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 1244622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1245622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 1246622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredName.FAMILY_NAME, StructuredName.SUFFIX 1247622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 12483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1249622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1250622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Parses the supplied display name, but only if the incoming values do 1251622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * not already contain structured name parts. Also, if the display name 1252622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * is not provided, generate one by concatenating first name and last 1253622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * name. 1254622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1255622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredNameComponents(ContentValues augmented, ContentValues update) { 125667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredName.DISPLAY_NAME); 1257622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 125867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 125967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1260622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1261622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 12628c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1263622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(name, unstruct); 1264622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.toValues(update); 126567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 126667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 126767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // We need to update the display name when any structured components 126867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // are specified, even when they are null, which is why we are checking 126967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // areAnySpecified. The touchedStruct in the condition is an optimization: 127067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // if there are non-null values, we know for a fact that some values are present. 12718c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 1272622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey name.fromValues(augmented); 12734cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao // As the name could be changed, let's guess the name style again. 12744cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao name.fullNameStyle = FullNameStyle.UNDEFINED; 12754cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mSplitter.guessNameStyle(name); 1276ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao int unadjustedFullNameStyle = name.fullNameStyle; 1277ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao name.fullNameStyle = mSplitter.getAdjustedFullNameStyle(name.fullNameStyle); 12785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov final String joined = mSplitter.join(name, true); 1279622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredName.DISPLAY_NAME, joined); 12805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 1281ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao update.put(StructuredName.FULL_NAME_STYLE, unadjustedFullNameStyle); 12825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov update.put(StructuredName.PHONETIC_NAME_STYLE, name.phoneticNameStyle); 12834cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } else if (touchedUnstruct && touchedStruct){ 1284d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov if (!update.containsKey(StructuredName.FULL_NAME_STYLE)) { 1285d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov update.put(StructuredName.FULL_NAME_STYLE, 1286d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov mSplitter.guessFullNameStyle(unstruct)); 12874cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 1288d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov if (!update.containsKey(StructuredName.PHONETIC_NAME_STYLE)) { 1289d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov update.put(StructuredName.PHONETIC_NAME_STYLE, 1290d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov mSplitter.guessPhoneticNameStyle(unstruct)); 12914cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 1292622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1293622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1294622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1295622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1296622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public class StructuredPostalRowHandler extends DataRowHandler { 1297622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mSplitter; 1298622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1299622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public StructuredPostalRowHandler(PostalSplitter splitter) { 1300622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey super(StructuredPostal.CONTENT_ITEM_TYPE); 1301622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter = splitter; 1302622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1303622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1304622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1305622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1306622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(values, values); 1307622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1308622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1309622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1310622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1311813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1312f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1313622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1314622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1315813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (augmented == null) { // No change 1316813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1317813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1318813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1319622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey fixStructuredPostalComponents(augmented, values); 1320f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana super.update(db, values, c, callerIsSyncAdapter); 1321813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 1322622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 1323622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1324622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1325622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Specific list of structured fields. 1326622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1327622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private final String[] STRUCTURED_FIELDS = new String[] { 1328622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.STREET, StructuredPostal.POBOX, StructuredPostal.NEIGHBORHOOD, 1329622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.CITY, StructuredPostal.REGION, StructuredPostal.POSTCODE, 1330622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey StructuredPostal.COUNTRY, 1331622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey }; 1332622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1333622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1334622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Prepares the given {@link StructuredPostal} row, building 1335622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link StructuredPostal#FORMATTED_ADDRESS} to match the structured 1336622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * values when missing. When structured components are missing, the 1337622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * unstructured value is assigned to {@link StructuredPostal#STREET}. 1338622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1339622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void fixStructuredPostalComponents(ContentValues augmented, ContentValues update) { 134067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final String unstruct = update.getAsString(StructuredPostal.FORMATTED_ADDRESS); 134167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 134267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 134367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 1344622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1345622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final PostalSplitter.Postal postal = new PostalSplitter.Postal(); 1346622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1347622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (touchedUnstruct && !touchedStruct) { 1348622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey mSplitter.split(postal, unstruct); 1349622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.toValues(update); 135067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } else if (!touchedUnstruct 135167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 135267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov // See comment in 1353622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey postal.fromValues(augmented); 1354622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final String joined = mSplitter.join(postal); 1355622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey update.put(StructuredPostal.FORMATTED_ADDRESS, joined); 13563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 13613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 13633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 13643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 13663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 13673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 13683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 13693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 13703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 13713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 13725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1373622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(values, values); 1374622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey return super.insert(db, rawContactId, values); 1375622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 13763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1377622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey @Override 1378813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1379f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1380622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final long dataId = c.getLong(DataUpdateQuery._ID); 1381622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final ContentValues augmented = getAugmentedValues(db, dataId, values); 1382813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (augmented == null) { // No change 1383813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1384813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1385622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey enforceTypeAndLabel(augmented, values); 1386813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return super.update(db, values, c, callerIsSyncAdapter); 1387622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 13883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1389622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey /** 1390622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * If the given {@link ContentValues} defines {@link #mTypeColumn}, 1391622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * enforce that {@link #mLabelColumn} only appears when type is 1392622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * {@link BaseTypes#TYPE_CUSTOM}. Exception is thrown otherwise. 1393622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 1394622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private void enforceTypeAndLabel(ContentValues augmented, ContentValues update) { 1395622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasType = !TextUtils.isEmpty(augmented.getAsString(mTypeColumn)); 1396622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey final boolean hasLabel = !TextUtils.isEmpty(augmented.getAsString(mLabelColumn)); 13973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1398622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey if (hasLabel && !hasType) { 1399622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey // When label exists, assert that some type is defined 1400622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey throw new IllegalArgumentException(mTypeColumn + " must be specified when " 1401622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey + mLabelColumn + " is defined."); 1402622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 14033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 14073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 14093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 14103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 14135ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1414a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String company = values.getAsString(Organization.COMPANY); 1415a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title = values.getAsString(Organization.TITLE); 1416a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 1417a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = super.insert(db, rawContactId, values); 1418a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka 141925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1420a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookupForOrganization(rawContactId, dataId, company, title); 1421a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka return dataId; 14223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 14243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 1425813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1426f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1427813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1428813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1429813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 143014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 143131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov boolean containsCompany = values.containsKey(Organization.COMPANY); 143231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov boolean containsTitle = values.containsKey(Organization.TITLE); 143331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov if (containsCompany || containsTitle) { 1434813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 1435813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1436813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 143731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov String company; 143831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 143931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov if (containsCompany) { 144031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov company = values.getAsString(Organization.COMPANY); 144131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } else { 144231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 144331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov company = DatabaseUtils.stringForQuery(db, 144431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov "SELECT " + Organization.COMPANY + 144531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " FROM " + Tables.DATA + 144631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " WHERE " + Data._ID + "=?", mSelectionArgs1); 144731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } 144831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 144931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov String title; 145031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov if (containsTitle) { 145131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov title = values.getAsString(Organization.TITLE); 145231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } else { 145331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 145431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov title = DatabaseUtils.stringForQuery(db, 145531168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov "SELECT " + Organization.TITLE + 145631168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " FROM " + Tables.DATA + 145731168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov " WHERE " + Data._ID + "=?", mSelectionArgs1); 145831168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } 145931168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 146031168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov deleteNameLookup(dataId); 146131168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov insertNameLookupForOrganization(rawContactId, dataId, company, title); 146231168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov 146331168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 146431168f49a3da9b9a9d5346f3d6a8098b76179c9cDmitri Plotnikov } 1465813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 146614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 146714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 146814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 146914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1470a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka long dataId = c.getLong(DataUpdateQuery._ID); 147114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 147214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 147314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 147425abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1475a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka deleteNameLookup(dataId); 147614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 147714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 147814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 147914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 14803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 14813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 14823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 14833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 14843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 14853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 14863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 14893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1490e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 1491e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1492e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 1493e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 1494e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1495e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1496e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 14975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1498813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String email = values.getAsString(Email.DATA); 149914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 150014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 150114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 150225abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1503813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String address = insertNameLookupForEmail(rawContactId, dataId, email); 1504813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (address != null) { 1505813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1506813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 150714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 150814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 150914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 151014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 1511813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1512f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1513813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1514813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1515813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 151614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1517b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov if (values.containsKey(Email.DATA)) { 1518813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 1519813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1520813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1521b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov String address = values.getAsString(Email.DATA); 1522b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov deleteNameLookup(dataId); 1523b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov insertNameLookupForEmail(rawContactId, dataId, address); 1524b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1525813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1526b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov } 1527813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1528813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 152914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 153014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 153114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 153214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 153314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 153414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 153514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 153614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 153714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1538f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 153925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1540813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 154114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1542e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1543e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1544e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 1545e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 1546e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 1547e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 1548e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 1549e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 1550e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 1551e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 1552e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1553e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1554e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1555e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 155614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public class NicknameDataRowHandler extends CommonDataRowHandler { 155714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 155814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public NicknameDataRowHandler() { 155914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov super(Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL); 156014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 156114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 156214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 156314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 156414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 156514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 156614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 156714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1568813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!TextUtils.isEmpty(nickname)) { 1569813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1570813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 1571813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1572813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 157314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return dataId; 157414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 157514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 157614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 1577813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1578f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 157914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 158014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 158114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1582813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1583813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1584813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 158514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1586b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov if (values.containsKey(Nickname.NAME)) { 1587b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov String nickname = values.getAsString(Nickname.NAME); 1588b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov deleteNameLookup(dataId); 1589b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov insertNameLookupForNickname(rawContactId, dataId, nickname); 1590b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1591813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1592b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov } 1593813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1594813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 159514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 159614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 159714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 159814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 159914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 160014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 160114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 160214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 160314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 1604f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov deleteNameLookup(dataId); 160525abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1606813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 160714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 160814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 160914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 161014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 16113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 16123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 16133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 16143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 16153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 16163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 16173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 16185ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 16190b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov long dataId; 16200b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 16210b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 1622813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String normalizedNumber = computeNormalizedNumber(number); 1623813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 16240b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 1625653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 16260b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1627285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 162825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1629813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (normalizedNumber != null) { 1630813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 1631813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 16320b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } else { 16330b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov dataId = super.insert(db, rawContactId, values); 16340b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1635653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return dataId; 1636653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1637653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1638653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1639813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1640f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1641813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String number = null; 1642813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov String normalizedNumber = null; 16430b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 1644813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov number = values.getAsString(Phone.NUMBER); 1645813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov normalizedNumber = computeNormalizedNumber(number); 1646813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 1647813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1648653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1649813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1650813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1651813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1652653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1653813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (values.containsKey(Phone.NUMBER)) { 1654813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long dataId = c.getLong(DataUpdateQuery._ID); 1655813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 16560b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber); 1657285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 165825abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1659813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 16600b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov } 1661813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 166214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov } 166314bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 166414bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov @Override 166514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 166614bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long dataId = c.getLong(DataDeleteQuery._ID); 166714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 166814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 166914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov int count = super.delete(db, c); 167014bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov 167114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov updatePhoneLookup(db, rawContactId, dataId, null, null); 1672285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updateHasPhoneNumber(db, rawContactId); 167325abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov fixRawContactDisplayName(db, rawContactId); 1674813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov triggerAggregation(rawContactId); 167514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov return count; 1676653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1677653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1678813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov private String computeNormalizedNumber(String number) { 1679e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String normalizedNumber = null; 1680e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1681e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 1682e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 1683653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return normalizedNumber; 1684653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1685e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 1686653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId, 1687653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov String number, String normalizedNumber) { 1688e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 1689653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 16905ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 1691653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); 1692e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 169336045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.MIN_MATCH, 169436045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov PhoneNumberUtils.toCallerIDMinMatch(number)); 169536045476d2cc7c9c2f985307e87cb6bbc4cfe434Dmitri Plotnikov 1696653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov db.replace(Tables.PHONE_LOOKUP, null, phoneValues); 1697653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 16984da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 16994da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=?", mSelectionArgs1); 1700e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 17013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 17023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 17033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 17043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 17053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 17063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 17073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 17083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 17093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 17103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 17113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 17123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 17133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 17143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 17153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 17163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 17173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 17183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1719653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public class GroupMembershipRowHandler extends DataRowHandler { 1720653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1721dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String SELECTION_RAW_CONTACT_ID = RawContacts._ID + "=?"; 1722dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1723dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private static final String QUERY_COUNT_FAVORITES_GROUP_MEMBERSHIPS_BY_RAW_CONTACT_ID = 1724dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana "SELECT COUNT(*) FROM " + Tables.DATA + " LEFT OUTER JOIN " + Tables .GROUPS 1725dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " ON " + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID 1726dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + "=" + GroupsColumns.CONCRETE_ID 1727dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " WHERE " + DataColumns.MIMETYPE_ID + "=?" 1728dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND " + Tables.DATA + "." + GroupMembership.RAW_CONTACT_ID + "=?" 1729dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND " + Groups.FAVORITES + "!=0"; 1730dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1731653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public GroupMembershipRowHandler() { 1732653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov super(GroupMembership.CONTENT_ITEM_TYPE); 1733653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1734653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1735653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1736653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1737653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, true); 17380be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1739dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (hasFavoritesGroupMembership(db, rawContactId)) { 1740dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateRawContactsStar(db, rawContactId, true /* starred */); 1741dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 17420be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 17430be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return dataId; 1744653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1745653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1746653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov @Override 1747813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1748f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 174914bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1750dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean wasStarred = hasFavoritesGroupMembership(db, rawContactId); 1751653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov resolveGroupSourceIdInValues(rawContactId, db, values, false); 1752813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1753813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1754813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1755dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean isStarred = hasFavoritesGroupMembership(db, rawContactId); 1756dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (wasStarred != isStarred) { 1757dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateRawContactsStar(db, rawContactId, isStarred); 1758dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 17590be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 1760813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 17610be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 17620be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 1763dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void updateRawContactsStar(SQLiteDatabase db, long rawContactId, boolean starred) { 1764dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ContentValues rawContactValues = new ContentValues(); 1765dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactValues.put(RawContacts.STARRED, starred ? 1 : 0); 1766dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (db.update(Tables.RAW_CONTACTS, rawContactValues, SELECTION_RAW_CONTACT_ID, 1767dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}) > 0) { 1768dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mContactAggregator.updateStarred(rawContactId); 1769dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1770dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1771dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 1772dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private boolean hasFavoritesGroupMembership(SQLiteDatabase db, long rawContactId) { 1773dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final long groupMembershipMimetypeId = mDbHelper 1774dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 1775dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean isStarred = 0 < DatabaseUtils 1776dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana .longForQuery(db, QUERY_COUNT_FAVORITES_GROUP_MEMBERSHIPS_BY_RAW_CONTACT_ID, 1777dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(groupMembershipMimetypeId), Long.toString(rawContactId)}); 1778dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return isStarred; 1779dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 1780dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 17810be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov @Override 17820be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 17830be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1784dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean wasStarred = hasFavoritesGroupMembership(db, rawContactId); 17850be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov int count = super.delete(db, c); 1786dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean isStarred = hasFavoritesGroupMembership(db, rawContactId); 1787dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (wasStarred && !isStarred) { 1788dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateRawContactsStar(db, rawContactId, false /* starred */); 1789dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 17900be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov updateVisibility(rawContactId); 17910be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov return count; 17920be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 17930be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov 17940be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov private void updateVisibility(long rawContactId) { 1795b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 17960be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov if (contactId != 0) { 1797b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateContactVisible(contactId); 17980be993f8ef0078b9825a5ffe6add08a6786d8dacDmitri Plotnikov } 1799653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1800653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1801653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void resolveGroupSourceIdInValues(long rawContactId, SQLiteDatabase db, 1802653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov ContentValues values, boolean isInsert) { 1803653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1804653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1805653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId && containsGroupId) { 1806653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1807653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 1808653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1809653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1810653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1811653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (!containsGroupSourceId && !containsGroupId) { 1812653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (isInsert) { 1813653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov throw new IllegalArgumentException( 1814653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1815653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov + "and GroupMembership.GROUP_ROW_ID"); 1816653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } else { 1817653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return; 1818653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1819653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1820653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1821653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (containsGroupSourceId) { 1822653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1823ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId, 1824ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.get(rawContactId)); 1825653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.remove(GroupMembership.GROUP_SOURCE_ID); 1826653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov values.put(GroupMembership.GROUP_ROW_ID, groupId); 1827653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1828653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1829653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } 1830653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1831a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public class PhotoDataRowHandler extends DataRowHandler { 1832a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1833a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public PhotoDataRowHandler() { 1834a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov super(Photo.CONTENT_ITEM_TYPE); 1835a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1836a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1837a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1838a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 1839a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long dataId = super.insert(db, rawContactId, values); 1840285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (!isNewRawContact(rawContactId)) { 1841285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1842285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 1843a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return dataId; 1844a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1845a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1846a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1847813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public boolean update(SQLiteDatabase db, ContentValues values, Cursor c, 1848f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana boolean callerIsSyncAdapter) { 1849a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 1850813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (!super.update(db, values, c, callerIsSyncAdapter)) { 1851813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return false; 1852813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } 1853813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov 1854a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1855813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return true; 1856a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1857a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1858a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov @Override 1859a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 1860a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 1861a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov int count = super.delete(db, c); 1862a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov mContactAggregator.updatePhotoId(db, rawContactId); 1863a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov return count; 1864a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1865a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 1866a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 1867ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov /** 1868ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * An entry in group id cache. It maps the combination of (account type, account name 1869ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov * and source id) to group row id. 1870ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov */ 1871ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov public class GroupIdCacheEntry { 1872ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType; 1873ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName; 1874ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String sourceId; 1875ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov long groupId; 1876ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 1877a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov 18783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 1879b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private ContactsDatabaseHelper mDbHelper; 188031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 18814097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 1882f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private NameLookupBuilder mNameLookupBuilder; 1883315dd702d006aedf2f867d3fe49e31e05e4f9a16Dmitri Plotnikov 1884622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private PostalSplitter mPostalSplitter; 1885622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 1886ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // We don't need a soft cache for groups - the assumption is that there will only 1887ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // be a small number of contact groups. The cache is keyed off source id. The value 1888ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov // is a list of groups with this group id. 1889ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache = Maps.newHashMap(); 1890ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 1891622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey private ContactAggregator mContactAggregator; 1892f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 1893a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 1894d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov private CommonNicknameCache mCommonNicknameCache; 1895a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 189620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 18971129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private CharArrayBuffer mCharArrayBuffer = new CharArrayBuffer(128); 18985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private NameSplitter.Name mName = new NameSplitter.Name(); 189973f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov private HashMap<String, Boolean> mAccountWritability = Maps.newHashMap(); 190020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 190109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private int mProviderStatus = ProviderStatus.STATUS_NORMAL; 190209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private long mEstimatedStorageRequirement = 0; 1903ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov private volatile CountDownLatch mAccessLatch; 190473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 1905ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private HashMap<Long, Account> mInsertedRawContacts = Maps.newHashMap(); 1906b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashSet<Long> mUpdatedRawContacts = Sets.newHashSet(); 1907a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private HashSet<Long> mDirtyRawContacts = Sets.newHashSet(); 1908b5a4add17815167d20a90645779df34cdf45280dFred Quintana private HashMap<Long, Object> mUpdatedSyncStates = Maps.newHashMap(); 1909de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov 19101a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey private boolean mVisibleTouched = false; 19111a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 191281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov private boolean mSyncToNetwork; 191381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 19144cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao private Locale mCurrentLocale; 1915d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 191673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 19174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 19184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1919de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov super.onCreate(); 1920ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov try { 1921ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return initialize(); 1922ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } catch (RuntimeException e) { 1923ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov Log.e(TAG, "Cannot start provider", e); 1924ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov return false; 1925ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 1926ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov } 192735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1928ea029fd79225640e49be82457b83b6b3a0279fd0Dmitri Plotnikov private boolean initialize() { 1929de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final Context context = getContext(); 1930b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper = (ContactsDatabaseHelper)getDatabaseHelper(); 1931a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 1932b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mDbHelper, this, mGlobalSearchSupport); 1933767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov mContactAggregator = new ContactAggregator(this, mDbHelper, 1934767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov createPhotoPriorityResolver(context)); 19350e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff mContactAggregator.setEnabled(SystemProperties.getBoolean(AGGREGATE_CONTACTS, true)); 1936a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1937b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mDb = mDbHelper.getWritableDatabase(); 1938653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 193951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov initForDefaultLocale(); 1940d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov 1941b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mSetPrimaryStatement = mDb.compileStatement( 1942653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1943653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_PRIMARY + "=(_id=?)" + 1944653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1945653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + "=?"); 1946653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1947b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mSetSuperPrimaryStatement = mDb.compileStatement( 1948653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "UPDATE " + Tables.DATA + 1949653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " SET " + Data.IS_SUPER_PRIMARY + "=(" + Data._ID + "=?)" + 1950653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=?" + 1951653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN (" + 1952653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts._ID + 1953653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1954653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + " =(" + 1955653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 1956653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 1957653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?))"); 1958653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 1959b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mRawContactDisplayNameUpdate = mDb.compileStatement( 196025abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 19615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov " SET " + 19625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_SOURCE + "=?," + 19635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_PRIMARY + "=?," + 19645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.DISPLAY_NAME_ALTERNATIVE + "=?," + 19655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME + "=?," + 19665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.PHONETIC_NAME_STYLE + "=?," + 19675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_PRIMARY + "=?," + 19685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov RawContacts.SORT_KEY_ALTERNATIVE + "=?" + 196925abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov " WHERE " + RawContacts._ID + "=?"); 19703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1971b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mLastStatusUpdate = mDb.compileStatement( 1972a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov "UPDATE " + Tables.CONTACTS + 1973a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " SET " + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" + 1974a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "(SELECT " + DataColumns.CONCRETE_ID + 1975a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " FROM " + Tables.STATUS_UPDATES + 1976a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.DATA + 1977a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + StatusUpdatesColumns.DATA_ID + "=" 1978a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + DataColumns.CONCRETE_ID + ")" + 1979a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 1980a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + DataColumns.CONCRETE_RAW_CONTACT_ID + "=" 1981a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID + ")" + 1982a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=?" + 19830a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ORDER BY " + StatusUpdates.STATUS_TIMESTAMP + " DESC," 19840a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + 1985a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " LIMIT 1)" + 1986a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov " WHERE " + ContactsColumns.CONCRETE_ID + "=?"); 1987e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 1988b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mNameLookupInsert = mDb.compileStatement("INSERT OR IGNORE INTO " + Tables.NAME_LOOKUP + "(" 1989f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + "," + NameLookupColumns.DATA_ID + "," 1990f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.NAME_TYPE + "," + NameLookupColumns.NORMALIZED_NAME 1991f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + ") VALUES (?,?,?,?)"); 1992b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mNameLookupDelete = mDb.compileStatement("DELETE FROM " + Tables.NAME_LOOKUP + " WHERE " 1993f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov + NameLookupColumns.DATA_ID + "=?"); 1994f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 1995b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusUpdateInsert = mDb.compileStatement( 1996a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT INTO " + Tables.STATUS_UPDATES + "(" 1997a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 19980a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 19990a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 20000a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 20010a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 20020a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?)"); 2003a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2004b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusUpdateReplace = mDb.compileStatement( 2005a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "INSERT OR REPLACE INTO " + Tables.STATUS_UPDATES + "(" 2006a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov + StatusUpdatesColumns.DATA_ID + ", " 20070a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_TIMESTAMP + "," 20080a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "," 20090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_RES_PACKAGE + "," 20100a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "," 20110a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + ")" + 20120a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " VALUES (?,?,?,?,?,?)"); 2013a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2014b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusUpdateAutoTimestamp = mDb.compileStatement( 2015a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 20160a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_TIMESTAMP + "=?," 20170a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS + "=?" + 2018a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?" 20190a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + " AND " + StatusUpdates.STATUS + "!=?"); 20200a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 2021b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusAttributionUpdate = mDb.compileStatement( 20220a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov "UPDATE " + Tables.STATUS_UPDATES + 20230a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " SET " + StatusUpdates.STATUS_RES_PACKAGE + "=?," 20240a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_ICON + "=?," 20250a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + StatusUpdates.STATUS_LABEL + "=?" + 20260a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 2027a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2028b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mStatusUpdateDelete = mDb.compileStatement( 2029a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov "DELETE FROM " + Tables.STATUS_UPDATES + 2030a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " WHERE " + StatusUpdatesColumns.DATA_ID + "=?"); 2031a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 2032f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // When setting NAME_VERIFIED to 1 on a raw contact, reset it to 0 2033f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // on all other raw contacts in the same aggregate 2034b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mResetNameVerifiedForOtherRawContacts = mDb.compileStatement( 2035f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov "UPDATE " + Tables.RAW_CONTACTS + 2036f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " SET " + RawContacts.NAME_VERIFIED + "=0" + 2037f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " WHERE " + RawContacts.CONTACT_ID + "=(" + 2038f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov "SELECT " + RawContacts.CONTACT_ID + 2039f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 2040f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " WHERE " + RawContacts._ID + "=?)" + 2041f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov " AND " + RawContacts._ID + "!=?"); 2042f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 2043f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdEmail = mDbHelper.getMimeTypeId(Email.CONTENT_ITEM_TYPE); 2044f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mMimeTypeIdIm = mDbHelper.getMimeTypeId(Im.CONTENT_ITEM_TYPE); 20451129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdStructuredName = mDbHelper.getMimeTypeId(StructuredName.CONTENT_ITEM_TYPE); 20461129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdOrganization = mDbHelper.getMimeTypeId(Organization.CONTENT_ITEM_TYPE); 20471129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdNickname = mDbHelper.getMimeTypeId(Nickname.CONTENT_ITEM_TYPE); 20481129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mMimeTypeIdPhone = mDbHelper.getMimeTypeId(Phone.CONTENT_ITEM_TYPE); 204904b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov 2050bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov verifyAccounts(); 2051bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov verifyLocale(); 2052bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 205365ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 205465ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov importLegacyContactsAsync(); 205565ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov } 205665ce381c2bb7ddcc3e7d3b8f5f7095831be97603Dmitri Plotnikov 2057b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return (mDb != null); 20584f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 20594f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2060ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao private void initDataRowHandlers() { 2061ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers = new HashMap<String, DataRowHandler>(); 2062ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao 2063ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 2064ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 2065ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 2066ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 2067ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 2068ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 2069ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 2070ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new NicknameDataRowHandler()); 2071ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 2072ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao new StructuredNameRowHandler(mNameSplitter)); 2073ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(StructuredPostal.CONTENT_ITEM_TYPE, 2074ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao new StructuredPostalRowHandler(mPostalSplitter)); 2075ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(GroupMembership.CONTENT_ITEM_TYPE, new GroupMembershipRowHandler()); 2076ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao mDataRowHandlers.put(Photo.CONTENT_ITEM_TYPE, new PhotoDataRowHandler()); 2077ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao } 207851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov /** 2079767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov * Visible for testing. 2080767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov */ 2081767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov /* package */ PhotoPriorityResolver createPhotoPriorityResolver(Context context) { 2082767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov return new PhotoPriorityResolver(context); 2083767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov } 2084767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov 2085767e109d6f08749b9ed202c0b71f3459eaae2115Dmitri Plotnikov /** 208651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * (Re)allocates all locale-sensitive structures. 208751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 208804b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov private void initForDefaultLocale() { 20894cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mCurrentLocale = getLocale(); 209004b7ce026c73077d9d982742bc662ea4b3ac74e7Dmitri Plotnikov mNameSplitter = mDbHelper.createNameSplitter(); 20914cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mNameLookupBuilder = new StructuredNameLookupBuilder(mNameSplitter); 20924cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao mPostalSplitter = new PostalSplitter(mCurrentLocale); 209351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mCommonNicknameCache = new CommonNicknameCache(mDbHelper.getReadableDatabase()); 2094cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao ContactLocaleUtils.getIntance().setLocale(mCurrentLocale); 2095ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao initDataRowHandlers(); 20964cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 20974cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao 20984cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao @Override 209951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov public void onConfigurationChanged(Configuration newConfig) { 210051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov initForDefaultLocale(); 210151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov verifyLocale(); 21024cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao } 210351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 2104c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov protected void verifyAccounts() { 2105c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov AccountManager.get(getContext()).addOnAccountsUpdatedListener(this, null, false); 2106c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov onAccountsUpdated(AccountManager.get(getContext()).getAccounts()); 2107c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov } 2108c1778ef6fa53b6bf08fd715b3ad70c052c5f1ce9Dmitri Plotnikov 210951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov /** 211051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * Verifies that the contacts database is properly configured for the current locale. 211151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * If not, changes the database locale to the current locale using an asynchronous task. 211251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * This needs to be done asynchronously because the process involves rebuilding 211351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * large data structures (name lookup, sort keys), which can take minutes on 211451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov * a large set of contacts. 211551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov */ 211651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void verifyLocale() { 2117f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 2118f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // The process is already running - postpone the change 2119f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov if (mProviderStatus == ProviderStatus.STATUS_CHANGING_LOCALE) { 2120f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov return; 2121f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov } 2122f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 212351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 212451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final String providerLocale = prefs.getString(PREF_LOCALE, null); 212551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov if (providerLocale == null) { 212651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov // The provider has just been created for the first time. There are no 212751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov // contacts in the database, so we can safely set locale on the UI thread. 212851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mDbHelper.setLocale(ContactsProvider2.this, mCurrentLocale); 212951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, mCurrentLocale.toString()).commit(); 213051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return; 213151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 213251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 213351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov final Locale currentLocale = mCurrentLocale; 213451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov if (currentLocale.toString().equals(providerLocale)) { 213551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return; 213651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 213751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 213851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov int providerStatus = mProviderStatus; 213951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_CHANGING_LOCALE); 214051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 214151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov AsyncTask<Integer, Void, Void> task = new AsyncTask<Integer, Void, Void>() { 214251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 214351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov int savedProviderStatus; 214451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 214551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov @Override 214651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected Void doInBackground(Integer... params) { 214751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov savedProviderStatus = params[0]; 214851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mDbHelper.setLocale(ContactsProvider2.this, currentLocale); 214951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov return null; 215051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 215151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 215251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov @Override 215351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void onPostExecute(Void result) { 215451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov prefs.edit().putString(PREF_LOCALE, currentLocale.toString()).commit(); 215551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov setProviderStatus(savedProviderStatus); 2156f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov 2157f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // Recursive invocation, needed to cover the case where locale 2158f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov // changes once and then changes again before the db upgrade is completed. 2159f0da835940ab6ae1aa37e0ba2ddd29c3117eb212Dmitri Plotnikov verifyLocale(); 216051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 216151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov }; 216251f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 216351f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov task.execute(providerStatus); 216451f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 216551f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 216631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 2167de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov @Override 2168b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 2169b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 217031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 217131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 2172013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov /* package */ NameSplitter getNameSplitter() { 2173013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov return mNameSplitter; 2174013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov } 2175013a0d6b3d392fb49d4618f2527b2ed3fec7d34fDmitri Plotnikov 21765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov /* Visible for testing */ 21775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov protected Locale getLocale() { 21785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov return Locale.getDefault(); 21795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 21805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 21813d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 2182b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov int version = Integer.parseInt(mDbHelper.getProperty(PROPERTY_CONTACTS_IMPORTED, "0")); 2183b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov return version < PROPERTY_CONTACTS_IMPORT_VERSION; 21843d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 21853d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2186568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 2187568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 2188568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2189568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2190568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 2191568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * Imports legacy contacts in a separate thread. As long as the import process is running 2192568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * all other access to the contacts is blocked. 2193568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 2194568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void importLegacyContactsAsync() { 2195bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Importing legacy contacts"); 2196bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADING); 2197bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (mAccessLatch == null) { 2198bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mAccessLatch = new CountDownLatch(1); 2199bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2200568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2201568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov Thread importThread = new Thread("LegacyContactImport") { 2202568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2203568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public void run() { 2204bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov LegacyContactImporter importer = getLegacyContactImporter(); 2205bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (importLegacyContacts(importer)) { 2206bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov onLegacyContactImportSuccess(); 2207bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 2208bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov onLegacyContactImportFailure(); 2209568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2210568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2211568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov }; 2212568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2213568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov importThread.start(); 2214568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2215568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2216bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 2217bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Unlocks the provider and declares that the import process is complete. 2218bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 2219bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportSuccess() { 2220bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 2221bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)getContext().getSystemService(Context.NOTIFICATION_SERVICE); 2222bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.cancel(LEGACY_IMPORT_FAILED_NOTIFICATION); 2223bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2224b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov // Store a property in the database indicating that the conversion process succeeded 2225b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov mDbHelper.setProperty(PROPERTY_CONTACTS_IMPORTED, 2226b2e27298ae54ec2215eadf98ecc100aedba98d1aDmitri Plotnikov String.valueOf(PROPERTY_CONTACTS_IMPORT_VERSION)); 2227bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_NORMAL); 2228bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mAccessLatch.countDown(); 2229bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mAccessLatch = null; 2230bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Completed import of legacy contacts"); 2231bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2232bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2233bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov /** 2234bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov * Announces the provider status and keeps the provider locked. 2235bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov */ 2236bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov private void onLegacyContactImportFailure() { 2237bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Context context = getContext(); 2238bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov NotificationManager nm = 2239bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); 2240bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2241bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // Show a notification 2242bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Notification n = new Notification(android.R.drawable.stat_notify_error, 2243bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_ticker), 2244bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov System.currentTimeMillis()); 2245bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.setLatestEventInfo(context, 2246bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_title), 2247bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov context.getString(R.string.upgrade_out_of_memory_notification_text), 2248bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov PendingIntent.getActivity(context, 0, new Intent(Intents.UI.LIST_DEFAULT), 0)); 2249bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov n.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; 2250bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2251bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov nm.notify(LEGACY_IMPORT_FAILED_NOTIFICATION, n); 2252bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2253bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov setProviderStatus(ProviderStatus.STATUS_UPGRADE_OUT_OF_MEMORY); 2254bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Log.v(TAG, "Failed to import legacy contacts"); 22553d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 22563d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 22573d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 2258568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 22590e8520cf7f15576ce4d66202203770086fd26a71Ken Shirriff boolean aggregatorEnabled = mContactAggregator.isEnabled(); 22603d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 22613d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 2262bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (importer.importContacts()) { 2263bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov 2264bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // TODO aggregate all newly added raw contacts 2265bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mContactAggregator.setEnabled(aggregatorEnabled); 2266bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return true; 2267bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 22683d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 22693d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 22703d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 2271bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov mEstimatedStorageRequirement = importer.getEstimatedStorageRequirement(); 2272bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return false; 22733d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 22743d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2275a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 2276a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 2277a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 2278a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 2279b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.wipeData(); 2280a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 2281a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2282568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov /** 2283568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * While importing and aggregating contacts, this content provider will 2284568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * block all attempts to change contacts data. In particular, it will hold 2285568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * up all contact syncs. As soon as the import process is complete, all 2286568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * processes waiting to write to the provider are unblocked and can proceed 2287568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov * to compete for the database transaction monitor. 2288568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov */ 2289568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov private void waitForAccess() { 2290ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov CountDownLatch latch = mAccessLatch; 2291ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov if (latch != null) { 2292ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov while (true) { 2293ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov try { 2294ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov latch.await(); 2295ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov mAccessLatch = null; 2296ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov return; 2297ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } catch (InterruptedException e) { 229881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov Thread.currentThread().interrupt(); 2299ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 2300ff065d085b794a0bf4be4cf6e87a67bf060e0319Dmitri Plotnikov } 2301568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2302568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2303568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2304568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2305568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 2306568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2307568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.insert(uri, values); 2308568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2309568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2310568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2311568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 2312bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (mAccessLatch != null) { 2313bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // We are stuck trying to upgrade contacts db. The only update request 2314bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // allowed in this case is an update of provider status, which will trigger 2315bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov // an attempt to upgrade contacts again. 2316bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov int match = sUriMatcher.match(uri); 2317bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (match == PROVIDER_STATUS && isLegacyContactImportNeeded()) { 2318bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov Integer newStatus = values.getAsInteger(ProviderStatus.STATUS); 2319bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov if (newStatus != null && newStatus == ProviderStatus.STATUS_UPGRADING) { 2320bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov importLegacyContactsAsync(); 2321bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 1; 2322bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } else { 2323bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov return 0; 2324bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2325bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2326bd578a748ab5bd74aa63511cce8769d5882f4651Dmitri Plotnikov } 2327568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2328568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.update(uri, values, selection, selectionArgs); 2329568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2330568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2331568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2332568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 2333568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2334568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.delete(uri, selection, selectionArgs); 2335568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2336568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 2337568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov @Override 2338568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 2339568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov throws OperationApplicationException { 2340568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov waitForAccess(); 2341568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov return super.applyBatch(operations); 2342568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov } 2343568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 23444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2345285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void onBeginTransaction() { 2346bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2347b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "onBeginTransaction"); 2348b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2349285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.onBeginTransaction(); 23501ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.clearPendingAggregations(); 2351b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 2352b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2353b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2354b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void clearTransactionalChanges() { 2355285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov mInsertedRawContacts.clear(); 2356b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.clear(); 2357df9db5e99572ce9760eb265683134c1f3293928fFred Quintana mUpdatedSyncStates.clear(); 2358a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDirtyRawContacts.clear(); 2359285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2360285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2361285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2362285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov protected void beforeTransactionCommit() { 23631129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 2364bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2365b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "beforeTransactionCommit"); 2366b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2367285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov super.beforeTransactionCommit(); 2368b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 23691ea29714ef8fdd62b71f265f27391c22f4a50340Fred Quintana mContactAggregator.aggregateInTransaction(mDb); 23701a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (mVisibleTouched) { 23711a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = false; 2372b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.updateAllVisible(); 23731a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey } 2374b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2375b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2376b5a4add17815167d20a90645779df34cdf45280dFred Quintana private void flushTransactionalChanges() { 2377bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 2378b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "flushTransactionChanges"); 2379b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 23801129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 238108e42c9c153a60bf2e7c71dd40bf84bb5fc93555Dmitri Plotnikov for (long rawContactId : mInsertedRawContacts.keySet()) { 2382d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov updateRawContactDisplayName(mDb, rawContactId); 2383d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov mContactAggregator.onRawContactInsert(mDb, rawContactId); 2384285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2385b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2386a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov if (!mDirtyRawContacts.isEmpty()) { 2387a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2388a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL); 2389a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov appendIds(mSb, mDirtyRawContacts); 2390a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 2391a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 2392a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov } 2393a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2394b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (!mUpdatedRawContacts.isEmpty()) { 2395a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.setLength(0); 2396a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL); 2397a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov appendIds(mSb, mUpdatedRawContacts); 2398a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mSb.append(")"); 2399a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDb.execSQL(mSb.toString()); 2400b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2401b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2402b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (Map.Entry<Long, Object> entry : mUpdatedSyncStates.entrySet()) { 2403b5a4add17815167d20a90645779df34cdf45280dFred Quintana long id = entry.getKey(); 24049d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana if (mDbHelper.getSyncState().update(mDb, id, entry.getValue()) <= 0) { 24059d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana throw new IllegalStateException( 24069d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana "unable to update sync state, does it still exist?"); 24079d9673d6a93926c337e23b7e2dcfb9aebc43e9abFred Quintana } 2408b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2409b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2410b5a4add17815167d20a90645779df34cdf45280dFred Quintana clearTransactionalChanges(); 2411b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2412b5a4add17815167d20a90645779df34cdf45280dFred Quintana 2413a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov /** 2414a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * Appends comma separated ids. 2415a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov * @param ids Should not be empty 2416a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov */ 2417a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov private void appendIds(StringBuilder sb, HashSet<Long> ids) { 2418b5a4add17815167d20a90645779df34cdf45280dFred Quintana for (long id : ids) { 2419a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(id).append(','); 2420b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2421a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov 2422a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.setLength(sb.length() - 1); // Yank the last comma 2423285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2424285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2425285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov @Override 2426cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov protected void notifyChange() { 242781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov notifyChange(mSyncToNetwork); 242881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = false; 242981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 243081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 243181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov protected void notifyChange(boolean syncToNetwork) { 243281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, 243381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov syncToNetwork); 2434cdbd854decda3f493b395c8867f2cd131d95d09fDmitri Plotnikov } 2435568904d1cc9acfabac78b6fcbf8a7d5115688174Dmitri Plotnikov 243651f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov protected void setProviderStatus(int status) { 243751f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov mProviderStatus = status; 243851f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov getContext().getContentResolver().notifyChange(ContactsContract.ProviderStatus.CONTENT_URI, 243951f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov null, false); 244051f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov } 244151f41be3b905c63ccffcdc82ec58cf5f7ded2c34Dmitri Plotnikov 2442285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov private boolean isNewRawContact(long rawContactId) { 2443ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return mInsertedRawContacts.containsKey(rawContactId); 2444285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 2445285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 24463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 24473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 24483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 24493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 24503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 24513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 24523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 24533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 24543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 24554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 2456de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected Uri insertInTransaction(Uri uri, ContentValues values) { 2457bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 24581129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Log.v(TAG, "insertInTransaction: " + uri + " " + values); 2459b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 2460f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2461f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 2462f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 2463f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana 2464a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 2465a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 246635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2467a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 246835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 2469b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov id = mDbHelper.getSyncState().insert(mDb, values); 247035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 247135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2472d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2473d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 24746bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 24756bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 24766bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 24775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 2478dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana id = insertRawContact(uri, values, callerIsSyncAdapter); 2479f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2480a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2481a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2482a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 24835ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 24845ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 2485f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2486f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2487a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2488a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2489a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2490a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 2491f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana id = insertData(values, callerIsSyncAdapter); 2492f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2493a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2494a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2495a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2496ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2497f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov id = insertGroup(uri, values, callerIsSyncAdapter); 2498f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 2499ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2500ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2501ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2502eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 25035aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey id = insertSettings(uri, values); 250443880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 2505eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 2506eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 2507eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 250882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 250982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov id = insertStatusUpdate(values); 25101f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 25111f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 25121f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2513a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 251481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 2515f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 2516a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2517a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 25187e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 25197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 25207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2522de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return ContentUris.withAppendedId(uri, id); 2523a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2524a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2525a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2526e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * If account is non-null then store it in the values. If the account is 2527e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * already specified in the values then it must be consistent with the 2528e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * account, if it is non-null. 2529e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * 2530e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param uri Current {@link Uri} being operated on. 2531e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @param values {@link ContentValues} to read and possibly update. 2532e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when only one of 2533e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_NAME} or 2534e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * {@link RawContacts#ACCOUNT_TYPE} is specified, leaving the 2535e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * other undefined. 2536e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * @throws IllegalArgumentException when {@link RawContacts#ACCOUNT_NAME} 2537e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * and {@link RawContacts#ACCOUNT_TYPE} are inconsistent between 2538e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey * the given {@link Uri} and {@link ContentValues}. 25397e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 2540e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey private Account resolveAccount(Uri uri, ContentValues values) throws IllegalArgumentException { 2541f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 2542f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 2543e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 2544f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2545f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 2546f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String valueAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 2547e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialValues = TextUtils.isEmpty(valueAccountName) 2548e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey ^ TextUtils.isEmpty(valueAccountType); 2549e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2550e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri || partialValues) { 2551e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 2552fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 2553fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 2554e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2555e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2556e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 2557e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 2558e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validUri = !TextUtils.isEmpty(accountName); 2559e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validValues = !TextUtils.isEmpty(valueAccountName); 2560e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 2561e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validValues && validUri) { 2562e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Check that accounts match when both present 2563e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean accountMatch = TextUtils.equals(accountName, valueAccountName) 2564e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey && TextUtils.equals(accountType, valueAccountType); 2565e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (!accountMatch) { 2566fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 2567fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "When both specified, ACCOUNT_NAME and ACCOUNT_TYPE must match", uri)); 2568e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 2569e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validUri) { 2570e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Fill values from Uri when not present 2571f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, accountName); 2572f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, accountType); 2573e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else if (validValues) { 2574f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountName = valueAccountName; 2575f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov accountType = valueAccountType; 2576e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } else { 2577e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return null; 2578f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 2579f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2580e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Use cached Account object when matches, otherwise create 2581f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mAccount == null 2582f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.name.equals(accountName) 2583f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov || !mAccount.type.equals(accountType)) { 2584f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mAccount = new Account(accountName, accountType); 2585035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 2586f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2587e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return mAccount; 25887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 2591d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 25926bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 25936bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 25946bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 25956bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 2596d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 2597de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new UnsupportedOperationException("Aggregate contacts are created automatically"); 25986bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 25996bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 26006bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 2601a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 2602a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2603f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param uri the values for the new row 2604f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * @param values the account this contact should be associated with. may be null. 2605dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana * @param callerIsSyncAdapter 2606a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2607a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2608dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private long insertRawContact(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 2609f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 2610f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 2611f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 2612f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2613e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 26147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 26153d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 26163d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 2617f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 26183d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 26193d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 2620f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long rawContactId = mDb.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, mValues); 2621f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = RawContacts.AGGREGATION_MODE_DEFAULT; 2622f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (mValues.containsKey(RawContacts.AGGREGATION_MODE)) { 2623f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov aggregationMode = mValues.getAsInteger(RawContacts.AGGREGATION_MODE); 2624f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 2625f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov mContactAggregator.markNewForAggregation(rawContactId, aggregationMode); 2626285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov 2627285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov // Trigger creation of a Contact based on this RawContact at the end of transaction 2628e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey mInsertedRawContacts.put(rawContactId, account); 2629f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 2630dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 2631dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 2632dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long starred = values.getAsLong(RawContacts.STARRED); 2633dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (starred != null && starred != 0) { 2634dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred != 0); 2635dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2636dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2637dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2638023b9437a3644e59309b8cfd12c6d84b98433f95Dmitri Plotnikov return rawContactId; 2639a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2640a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2641dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void addAutoAddMembership(long rawContactId) { 2642dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_AUTO_ADD_GROUPS_BY_RAW_CONTACT_ID, 2643dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 2644dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 2645dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 2646dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2647dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2648dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2649dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private Long findGroupByRawContactId(String selection, long rawContactId) { 2650dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Cursor c = mDb.query(Tables.GROUPS + "," + Tables.RAW_CONTACTS, PROJECTION_GROUP_ID, 2651dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection, 2652dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}, 2653dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana null /* groupBy */, null /* having */, null /* orderBy */); 2654dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 2655dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (c.moveToNext()) { 2656dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return c.getLong(0); 2657dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2658dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return null; 2659dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 2660dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana c.close(); 2661dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2662dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2663dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2664dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void updateFavoritesMembership(long rawContactId, boolean isStarred) { 2665dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final Long groupId = findGroupByRawContactId(SELECTION_FAVORITES_GROUPS_BY_RAW_CONTACT_ID, 2666dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana rawContactId); 2667dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (groupId != null) { 2668dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (isStarred) { 2669dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, groupId); 2670dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 2671dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana deleteDataGroupMembership(rawContactId, groupId); 2672dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2673dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2674dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2675dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2676dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void insertDataGroupMembership(long rawContactId, long groupId) { 2677dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ContentValues groupMembershipValues = new ContentValues(); 2678dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.GROUP_ROW_ID, groupId); 2679dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(GroupMembership.RAW_CONTACT_ID, rawContactId); 2680dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana groupMembershipValues.put(DataColumns.MIMETYPE_ID, 2681dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDbHelper.getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 2682dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDb.insert(Tables.DATA, null, groupMembershipValues); 2683dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2684dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2685dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void deleteDataGroupMembership(long rawContactId, long groupId) { 2686dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final String[] selectionArgs = { 2687dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(mDbHelper.getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)), 2688dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(groupId), 2689dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Long.toString(rawContactId)}; 2690dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mDb.delete(Tables.DATA, SELECTION_GROUPMEMBERSHIP_DATA, selectionArgs); 2691dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 2692dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 2693a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 2694a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 2695a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 2696a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 2697a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 2698a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 2699f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private long insertData(ContentValues values, boolean callerIsSyncAdapter) { 2700a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 2701de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.clear(); 2702de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.putAll(values); 270367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2704de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 270520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2706de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace package with internal mapping 2707de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 2708de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (packageName != null) { 2709b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 2710de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 2711de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 2712508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 2713de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Replace mimetype with internal mapping 2714de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 2715de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 2716de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 2717de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov } 27184097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 2719b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.getMimeTypeId(mimeType)); 2720de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 2721a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2722a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 2723a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov id = rowHandler.insert(mDb, rawContactId, mValues); 2724f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 2725de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov setRawContactDirty(rawContactId); 2726a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2727b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedRawContacts.add(rawContactId); 2728a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 27294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 27304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 27318e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov private void triggerAggregation(long rawContactId) { 27328e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (!mContactAggregator.isEnabled()) { 27338e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov return; 27348e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 27358e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 2736b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov int aggregationMode = mDbHelper.getAggregationMode(rawContactId); 2737f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 27388e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 27398e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov break; 27408e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 27418e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: { 274269cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, aggregationMode, false); 2743f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 27448e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 27458e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov 27468e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_SUSPENDED: { 2747b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 2748f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 27498e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov if (contactId != 0) { 27508e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 27518e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2752f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 27538e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2754f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2755c100221f706afc08409e8317a27d6850b11c54d3Omari Stephens case RawContacts.AGGREGATION_MODE_IMMEDIATE: { 2756b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId = mDbHelper.getContactId(rawContactId); 27578e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov mContactAggregator.aggregateContact(mDb, rawContactId, contactId); 2758f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 27598e45e5f2142db78941b095f7418cc05b71668094Dmitri Plotnikov } 2760f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2761f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 2762f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 2763a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 27645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 27659261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 27669261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 27675ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 27689261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 27699261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 27709261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 27719261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 27729261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 2773ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId, 2774ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Account account) { 2775ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2776ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (account == null) { 27774da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 2778ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Cursor c = db.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, 27794da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov RawContacts._ID + "=?", mSelectionArgs1, null, null, null); 2780ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov try { 2781ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (c.moveToFirst()) { 2782ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = c.getString(RawContactsQuery.ACCOUNT_NAME); 2783ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = c.getString(RawContactsQuery.ACCOUNT_TYPE); 2784ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 2785ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov account = new Account(accountName, accountType); 2786ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 27879261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2788ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } finally { 2789ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov c.close(); 27909261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 27919261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2792ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 27939261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 27949261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 2795ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov + "has a sourceid the the contact must be associated with " 27969261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 27979261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 27989261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 2799ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ArrayList<GroupIdCacheEntry> entries = mGroupIdCache.get(sourceId); 2800ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (entries == null) { 2801ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entries = new ArrayList<GroupIdCacheEntry>(1); 2802ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.put(sourceId, entries); 2803ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2804ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2805ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov int count = entries.size(); 2806ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov for (int i = 0; i < count; i++) { 2807ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov GroupIdCacheEntry entry = entries.get(i); 2808ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (entry.accountName.equals(account.name) && entry.accountType.equals(account.type)) { 2809ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return entry.groupId; 2810ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2811ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov } 2812ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2813ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov GroupIdCacheEntry entry = new GroupIdCacheEntry(); 2814ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.accountName = account.name; 2815ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.accountType = account.type; 2816ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.sourceId = sourceId; 2817ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entries.add(0, entry); 2818ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 28199261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 28205ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 2821ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov Cursor c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 28229261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 2823df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[]{sourceId, account.name, account.type}, null, null, null); 28249261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 2825ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov if (c.moveToFirst()) { 2826ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.groupId = c.getLong(0); 28279261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 28289261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 2829df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.name); 2830df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.type); 28319261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 28329261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 28339261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 28349261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 28359261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 28369261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2837ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov entry.groupId = groupId; 28389261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 28399261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 28409261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 28419261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 2842ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 2843ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov return entry.groupId; 28449261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 28459261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 2846d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov private interface DisplayNameQuery { 28471129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov public static final String RAW_SQL = 28481129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov "SELECT " 28491129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + DataColumns.MIMETYPE_ID + "," 28501129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + Data.IS_PRIMARY + "," 28511129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov + Data.DATA1 + "," 28525dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA2 + "," 28535dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA3 + "," 28545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA4 + "," 28555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA5 + "," 28565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA6 + "," 28575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA7 + "," 28585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA8 + "," 28595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA9 + "," 28605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA10 + "," 28615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov + Data.DATA11 + 28621129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " FROM " + Tables.DATA + 28631129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " WHERE " + Data.RAW_CONTACT_ID + "=?" + 28641129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov " AND (" + Data.DATA1 + " NOT NULL OR " + 28651129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Organization.TITLE + " NOT NULL)"; 2866d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2867d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int MIMETYPE = 0; 2868d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov public static final int IS_PRIMARY = 1; 28695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int DATA1 = 2; 28705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int GIVEN_NAME = 3; // data2 28715dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int FAMILY_NAME = 4; // data3 28725dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PREFIX = 5; // data4 28735dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int TITLE = 5; // data4 28745dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int MIDDLE_NAME = 6; // data5 28755dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int SUFFIX = 7; // data6 28765dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_GIVEN_NAME = 8; // data7 28775dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_MIDDLE_NAME = 9; // data8 28785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int ORGANIZATION_PHONETIC_NAME = 9; // data8 28795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_FAMILY_NAME = 10; // data9 28805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int FULL_NAME_STYLE = 11; // data10 28815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int ORGANIZATION_PHONETIC_NAME_STYLE = 11; // data10 28825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov public static final int PHONETIC_NAME_STYLE = 12; // data11 2883d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2884d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2885d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov /** 2886d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov * Updates a raw contact display name based on data rows, e.g. structured name, 2887d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov * organization, email etc. 2888d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov */ 2889ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateRawContactDisplayName(SQLiteDatabase db, long rawContactId) { 2890bca1c8b44f99528fc123d5547723e44771e8e934Mike Lockwood int bestDisplayNameSource = DisplayNameSources.UNDEFINED; 28915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov NameSplitter.Name bestName = null; 28925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String bestDisplayName = null; 28935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String bestPhoneticName = null; 28945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 2895d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 28961129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 28971129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Cursor c = db.rawQuery(DisplayNameQuery.RAW_SQL, mSelectionArgs1); 2898d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov try { 2899d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov while (c.moveToNext()) { 29001129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov int mimeType = c.getInt(DisplayNameQuery.MIMETYPE); 29015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int source = getDisplayNameSource(mimeType); 29025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (source < bestDisplayNameSource || source == DisplayNameSources.UNDEFINED) { 29035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov continue; 29045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 29051129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 29065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (source == bestDisplayNameSource && c.getInt(DisplayNameQuery.IS_PRIMARY) == 0) { 29075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov continue; 2908d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 29091129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 29105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mimeType == mMimeTypeIdStructuredName) { 29115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov NameSplitter.Name name; 29125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestName != null) { 29135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name = new NameSplitter.Name(); 29145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 29155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name = mName; 29165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.clear(); 29175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 29185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.prefix = c.getString(DisplayNameQuery.PREFIX); 29195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.givenNames = c.getString(DisplayNameQuery.GIVEN_NAME); 29205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.middleName = c.getString(DisplayNameQuery.MIDDLE_NAME); 29215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.familyName = c.getString(DisplayNameQuery.FAMILY_NAME); 29225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.suffix = c.getString(DisplayNameQuery.SUFFIX); 29235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.fullNameStyle = c.isNull(DisplayNameQuery.FULL_NAME_STYLE) 29245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? FullNameStyle.UNDEFINED 29255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.FULL_NAME_STYLE); 29265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticFamilyName = c.getString(DisplayNameQuery.PHONETIC_FAMILY_NAME); 29275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticMiddleName = c.getString(DisplayNameQuery.PHONETIC_MIDDLE_NAME); 29285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticGivenName = c.getString(DisplayNameQuery.PHONETIC_GIVEN_NAME); 29295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov name.phoneticNameStyle = c.isNull(DisplayNameQuery.PHONETIC_NAME_STYLE) 29305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? PhoneticNameStyle.UNDEFINED 29315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.PHONETIC_NAME_STYLE); 29325dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (!name.isEmpty()) { 29335dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayNameSource = source; 29345dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestName = name; 29355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 29365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else if (mimeType == mMimeTypeIdOrganization) { 29375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied = 0; 29385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.DATA1, mCharArrayBuffer); 29395dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 2940d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov bestDisplayNameSource = source; 29411129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 29421129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 29435dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = c.getString(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME); 29445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = 29455dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.isNull(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME_STYLE) 29465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov ? PhoneticNameStyle.UNDEFINED 29475dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov : c.getInt(DisplayNameQuery.ORGANIZATION_PHONETIC_NAME_STYLE); 29485dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 29495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.TITLE, mCharArrayBuffer); 29505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 29511129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayNameSource = source; 29521129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 29531129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 29545dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = null; 29555dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 29561129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 2957d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 29585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 29595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // Display name is at DATA1 in all other types. 29605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov // This is ensured in the constructor. 29615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 29625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied = 0; 29635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov c.copyStringToBuffer(DisplayNameQuery.DATA1, mCharArrayBuffer); 29645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (mCharArrayBuffer.sizeCopied != 0) { 29655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayNameSource = source; 29665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestDisplayName = new String(mCharArrayBuffer.data, 0, 29675dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mCharArrayBuffer.sizeCopied); 29685dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = null; 29695dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = PhoneticNameStyle.UNDEFINED; 29705dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 2971d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2972d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2973d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 2974d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } finally { 2975d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov c.close(); 2976d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 2977d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 29785dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNamePrimary; 29795dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNameAlternative; 29805dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String sortKeyPrimary = null; 29815dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String sortKeyAlternative = null; 29825dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int displayNameStyle = FullNameStyle.UNDEFINED; 29835dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 29845dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestDisplayNameSource == DisplayNameSources.STRUCTURED_NAME) { 29855dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = bestName.fullNameStyle; 29865dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.CJK 29875dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov || displayNameStyle == FullNameStyle.UNDEFINED) { 29885dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedFullNameStyle(displayNameStyle); 29895dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestName.fullNameStyle = displayNameStyle; 29905dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 29915dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 29925dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNamePrimary = mNameSplitter.join(bestName, true); 29935dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameAlternative = mNameSplitter.join(bestName, false); 29945dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 29955dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticName = mNameSplitter.joinPhoneticName(bestName); 29965dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = bestName.phoneticNameStyle; 29975dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 29985dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNamePrimary = displayNameAlternative = bestDisplayName; 29995dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 30005dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 30015dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestPhoneticName != null) { 30025dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = sortKeyAlternative = bestPhoneticName; 30035dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (bestPhoneticNameStyle == PhoneticNameStyle.UNDEFINED) { 30045dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bestPhoneticNameStyle = mNameSplitter.guessPhoneticNameStyle(bestPhoneticName); 30055dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 30065dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 30075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.UNDEFINED) { 30085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.guessFullNameStyle(bestDisplayName); 30095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (displayNameStyle == FullNameStyle.UNDEFINED 30105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov || displayNameStyle == FullNameStyle.CJK) { 30115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedNameStyleBasedOnPhoneticNameStyle( 30125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle, bestPhoneticNameStyle); 30135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 30145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameStyle = mNameSplitter.getAdjustedFullNameStyle(displayNameStyle); 30155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 3016ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao if (displayNameStyle == FullNameStyle.CHINESE || 3017ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao displayNameStyle == FullNameStyle.CJK) { 30185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = sortKeyAlternative = 3019cdd03b2ba03718a7fa85663a2438136284a1557cBai Tao ContactLocaleUtils.getIntance().getSortKey( 3020ee0e6b105832366143e4ddb30beb5bb0e5c81ec5Bai Tao displayNamePrimary, displayNameStyle); 30215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 30225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 30235dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 30245dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (sortKeyPrimary == null) { 30255dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary = displayNamePrimary; 30265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyAlternative = displayNameAlternative; 30275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 30285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 30295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov setDisplayName(rawContactId, bestDisplayNameSource, displayNamePrimary, 30305dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov displayNameAlternative, bestPhoneticName, bestPhoneticNameStyle, 30315dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov sortKeyPrimary, sortKeyAlternative); 3032d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov } 3033d0f63551e3147babcebde5326b31285d7bdf6739Dmitri Plotnikov 30341129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov private int getDisplayNameSource(int mimeTypeId) { 30351129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov if (mimeTypeId == mMimeTypeIdStructuredName) { 30361129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.STRUCTURED_NAME; 30371129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdEmail) { 30381129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.EMAIL; 30391129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdPhone) { 30401129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.PHONE; 30411129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdOrganization) { 30421129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.ORGANIZATION; 30431129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else if (mimeTypeId == mMimeTypeIdNickname) { 30441129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.NICKNAME; 30451129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } else { 30461129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov return DisplayNameSources.UNDEFINED; 30471129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 30481129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov } 30491129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov 30509261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 305120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 305220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 3053f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) { 305420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 305520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3056de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 3057de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 305814bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, selection, selectionArgs, null); 3059de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov try { 3060de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov while(c.moveToNext()) { 306114bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 306214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 3063a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 3064a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov count += rowHandler.delete(mDb, c); 3065f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 306688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov setRawContactDirty(rawContactId); 306788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov } 306820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 306920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 3070de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov c.close(); 307120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 307220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 307320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 307420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 307520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 307688e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov /** 307788e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov * Delete a data row provided that it is one of the allowed mime types. 307888e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov */ 307920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 3080f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 308188e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 308288e5f4d32aa9cd3af0ac9654de479f1b8113f712Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 30834da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 30844da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataDeleteQuery.COLUMNS, Data._ID + "=?", 30854da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1, null); 3086f992bfab334b760d36a053fc0b439382dcfb51adDmitri Plotnikov 308720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 308820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 308920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 309020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 309120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 309214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov String mimeType = c.getString(DataDeleteQuery.MIMETYPE); 309320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 309420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 309520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 309620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 309720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 309820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 309920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 310020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 310120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 31027a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 310320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 310420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 310520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 3106a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 3107813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return rowHandler.delete(mDb, c); 310820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 310920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 311020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 311120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 311220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 311320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 3114ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 3115ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 3116f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private long insertGroup(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { 3117f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.clear(); 3118f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.putAll(values); 3119f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 3120e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final Account account = resolveAccount(uri, mValues); 3121ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3122ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 3123f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String packageName = mValues.getAsString(Groups.RES_PACKAGE); 312467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 3125f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(GroupsColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 312667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 3127f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.remove(Groups.RES_PACKAGE); 3128ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3129dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final boolean isFavoritesGroup = mValues.getAsLong(Groups.FAVORITES) != null 3130dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana ? mValues.getAsLong(Groups.FAVORITES) != 0 3131dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana : false; 3132dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3133f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter) { 3134f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov mValues.put(Groups.DIRTY, 1); 313573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 313673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3137f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov long result = mDb.insert(Tables.GROUPS, Groups.TITLE, mValues); 3138ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 3139dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && isFavoritesGroup) { 3140dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // add all starred raw contacts to this group 3141dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String selection; 3142dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs; 3143dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (account == null) { 3144dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + " IS NULL AND " 3145dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContacts.ACCOUNT_TYPE + " IS NULL"; 3146dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selectionArgs = null; 3147dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 3148dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection = RawContacts.ACCOUNT_NAME + "=? AND " 3149dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + RawContacts.ACCOUNT_TYPE + "=?"; 3150dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selectionArgs = new String[]{account.name, account.type}; 3151dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3152dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Cursor c = mDb.query(Tables.RAW_CONTACTS, 3153dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{RawContacts._ID, RawContacts.STARRED}, 3154dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana selection, selectionArgs, null, null, null); 3155dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (c.moveToNext()) { 3156dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (c.getLong(1) != 0) { 3157dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana final long rawContactId = c.getLong(0); 3158dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana insertDataGroupMembership(rawContactId, result); 3159dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana setRawContactDirty(rawContactId); 3160dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3161dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3162dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3163dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3164f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (mValues.containsKey(Groups.GROUP_VISIBLE)) { 31651a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3166ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey } 3167ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey 3168ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey return result; 3169ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3170ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 31715aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private long insertSettings(Uri uri, ContentValues values) { 3172e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final long id = mDb.insert(Tables.SETTINGS, null, values); 31735aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey 31741a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 31751a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3176e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 31771a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey 3178e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return id; 3179e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3180e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3181ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 318282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov * Inserts a status update. 31831f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 318482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov public long insertStatusUpdate(ContentValues values) { 318582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov final String handle = values.getAsString(StatusUpdates.IM_HANDLE); 31860a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL); 31874dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov String customProtocol = null; 31884dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov 31890a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) { 319082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL); 31914dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov if (TextUtils.isEmpty(customProtocol)) { 31924dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov throw new IllegalArgumentException( 31934dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov "CUSTOM_PROTOCOL is required when PROTOCOL=PROTOCOL_CUSTOM"); 31944dcd106ccc27dbbfaae86baf0cd57beb42c27cccDmitri Plotnikov } 31951f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 31961f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3197dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long rawContactId = -1; 3198dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton long contactId = -1; 319982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Long dataId = values.getAsLong(StatusUpdates.DATA_ID); 3200f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.setLength(0); 32012526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.clear(); 3202dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (dataId != null) { 3203dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the contact info for the given data row. 3204dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 32052526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(Tables.DATA + "." + Data._ID + "=?"); 32062526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(dataId)); 32071f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 3208dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // Lookup the data row to attach this presence update to 3209dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 32100a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(handle) || protocol == null) { 32110a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov throw new IllegalArgumentException("PROTOCOL and IM_HANDLE are required"); 32120a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 32130a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3214dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton // TODO: generalize to allow other providers to match against email 3215dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == protocol; 3216dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton 32172526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov String mimeTypeIdIm = String.valueOf(mMimeTypeIdIm); 3218dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (matchEmail) { 32192526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov String mimeTypeIdEmail = String.valueOf(mMimeTypeIdEmail); 3220f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3221f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // The following hack forces SQLite to use the (mimetype_id,data1) index, otherwise 3222f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the "OR" conjunction confuses it and it switches to a full scan of 3223f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // the raw_contacts table. 3224f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov 3225f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // This code relies on the fact that Im.DATA and Email.DATA are in fact the same 3226f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov // column - Data.DATA1 32272526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + " IN (?,?)" + 32282526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Data.DATA1 + "=?" + 32292526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND ((" + DataColumns.MIMETYPE_ID + "=? AND " + Im.PROTOCOL + "=?"); 32302526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 32312526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32322526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 32332526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32342526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 3235dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 32362526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 32372526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3238dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 32392526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(") OR (" + DataColumns.MIMETYPE_ID + "=?))"); 32402526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdEmail); 3241dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } else { 32422526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(DataColumns.MIMETYPE_ID + "=?" + 32432526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.PROTOCOL + "=?" + 32442526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov " AND " + Im.DATA + "=?"); 32452526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(mimeTypeIdIm); 32462526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(String.valueOf(protocol)); 32472526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(handle); 3248dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton if (customProtocol != null) { 32492526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + Im.CUSTOM_PROTOCOL + "=?"); 32502526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(customProtocol); 3251dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 3252dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 32531f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 325482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.DATA_ID)) { 32552526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.append(" AND " + DataColumns.CONCRETE_ID + "=?"); 32562526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSelectionArgs.add(values.getAsString(StatusUpdates.DATA_ID)); 3257dea2b6389abf1ae0448ae047b4b0a9e423381d77Jeff Hamilton } 325870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 3259f8b937f62fb80445bf59b2e504d765bcab746557Dmitri Plotnikov mSb.append(" AND ").append(getContactsRestrictions()); 326070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 32611f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 32621f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 3263de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 32642526f94e532ac973c846db0099f94b375a23be93Dmitri Plotnikov mSb.toString(), mSelectionArgs.toArray(EMPTY_STRING_ARRAY), null, null, 3265c03e723e7b07434a3e60454606bc18e2df4ee06bDmitri Plotnikov Contacts.IN_VISIBLE_GROUP + " DESC, " + Data.RAW_CONTACT_ID); 32661f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 326767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 32685ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 3269e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 32701f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 32711f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 32721f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 32731f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 32741f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 327531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 327631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 327731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 32781f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 32791f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 328082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.PRESENCE)) { 3281a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (customProtocol == null) { 3282a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // We cannot allow a null in the custom protocol field, because SQLite3 does not 3283a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // properly enforce uniqueness of null values 3284a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov customProtocol = ""; 3285a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3286a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3287a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.clear(); 328882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.DATA_ID, dataId); 3289a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.RAW_CONTACT_ID, rawContactId); 3290a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mValues.put(PresenceColumns.CONTACT_ID, contactId); 329182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PROTOCOL, protocol); 329282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.CUSTOM_PROTOCOL, customProtocol); 329382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_HANDLE, handle); 329482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.IM_ACCOUNT)) { 329582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.IM_ACCOUNT, values.getAsString(StatusUpdates.IM_ACCOUNT)); 3296a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 329782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov mValues.put(StatusUpdates.PRESENCE, 329882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov values.getAsString(StatusUpdates.PRESENCE)); 32991f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 3300a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // Insert the presence update 3301a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mDb.replace(Tables.PRESENCE, null, mValues); 3302a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3303e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 33040a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 330582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (values.containsKey(StatusUpdates.STATUS)) { 330682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String status = values.getAsString(StatusUpdates.STATUS); 33070a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String resPackage = values.getAsString(StatusUpdates.STATUS_RES_PACKAGE); 33080a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Integer labelResource = values.getAsInteger(StatusUpdates.STATUS_LABEL); 33090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 33100a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov if (TextUtils.isEmpty(resPackage) 33110a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && (labelResource == null || labelResource == 0) 33120a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov && protocol != null) { 33130a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov labelResource = Im.getProtocolLabelResource(protocol); 33140a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 33150a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 33160a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov Long iconResource = values.getAsLong(StatusUpdates.STATUS_ICON); 33170a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov // TODO compute the default icon based on the protocol 33180a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3319a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (TextUtils.isEmpty(status)) { 3320a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.bindLong(1, dataId); 3321a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateDelete.execute(); 332282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } else if (values.containsKey(StatusUpdates.STATUS_TIMESTAMP)) { 332382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov long timestamp = values.getAsLong(StatusUpdates.STATUS_TIMESTAMP); 3324a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(1, dataId); 3325a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.bindLong(2, timestamp); 33265dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateReplace, 3, status); 33275dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateReplace, 4, resPackage); 33285dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateReplace, 5, iconResource); 33295dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateReplace, 6, labelResource); 3330a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateReplace.execute(); 3331a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } else { 3332a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3333a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov try { 3334a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.bindLong(1, dataId); 33355dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateInsert, 2, status); 33365dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateInsert, 3, resPackage); 33375dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateInsert, 4, iconResource); 33385dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusUpdateInsert, 5, labelResource); 3339a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateInsert.executeInsert(); 3340a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } catch (SQLiteConstraintException e) { 3341a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov // The row already exists - update it 33420a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov long timestamp = System.currentTimeMillis(); 3343a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(1, timestamp); 33445dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateAutoTimestamp, 2, status); 3345a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.bindLong(3, dataId); 33465dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusUpdateAutoTimestamp, 4, status); 3347a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mStatusUpdateAutoTimestamp.execute(); 33480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 33495dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mStatusAttributionUpdate, 1, resPackage); 33505dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusAttributionUpdate, 2, iconResource); 33515dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindLong(mStatusAttributionUpdate, 3, labelResource); 33520a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.bindLong(4, dataId); 33530a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov mStatusAttributionUpdate.execute(); 3354a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3355e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3356e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 3357bffeabdf3dcf58f963ad1bb4d3e6e51f3ac16cfdDmitri Plotnikov 3358a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov if (contactId != -1) { 3359a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(1, contactId); 3360a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.bindLong(2, contactId); 3361a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov mLastStatusUpdate.execute(); 3362a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov } 3363a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov 3364a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov return dataId; 33651f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 33661f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 33674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3368de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { 3369bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3370b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "deleteInTransaction: " + uri); 3371b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3372b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3373f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3374f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 3375508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 3376508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 337735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3378b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selection, selectionArgs); 337935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3380b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: 3381b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3382b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3383b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 3384b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().delete(mDb, selectionWithId, selectionArgs); 3385b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3386cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov case CONTACTS: { 3387cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov // TODO 3388cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return 0; 3389cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3390cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3391d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3392d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 3393dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 33946bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 33956bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 33969fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP: { 33972e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 33982e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 33992e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 3400fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 3401fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 34022e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 34032e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 34042e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 3405dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 34062e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 34072e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 34089fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann case CONTACTS_LOOKUP_ID: { 34099fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // lookup contact by id and lookup key to see if they still match the actual record 34109fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann long contactId = ContentUris.parseId(uri); 34119fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final List<String> pathSegments = uri.getPathSegments(); 34129fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final String lookupKey = pathSegments.get(2); 34139fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 34149fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann setTablesAndProjectionMapForContacts(lookupQb, uri, null); 34159fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann String[] args; 34169fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (selectionArgs == null) { 34179fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[2]; 34189fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 34199fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args = new String[selectionArgs.length + 2]; 34209fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 34219fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34229fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann args[0] = String.valueOf(contactId); 342360de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann args[1] = Uri.encode(lookupKey); 34249fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 34259fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 34269fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann Cursor c = query(db, lookupQb, null, selection, args, null, null, null); 34279fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann try { 34289fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann if (c.getCount() == 1) { 34299fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // contact was unmodified so go ahead and delete it 3430dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return deleteContact(contactId, callerIsSyncAdapter); 34319fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } else { 34329fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // row was changed (e.g. the merging might have changed), we got multiple 34339fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann // rows or the supplied selection filtered the record out 34349fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann return 0; 34359fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34369fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } finally { 34379fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann c.close(); 34389fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34399fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann } 34409fcf109b56cec0aad05322a3b4594228ea06d859Daniel Lehmann 34412971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case RAW_CONTACTS: { 34422971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 3443fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, 3444fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov new String[]{RawContacts._ID, RawContacts.CONTACT_ID}, 3445e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 34462971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 34472971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 34482971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = c.getLong(0); 3449fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov long contactId = c.getLong(1); 3450fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov numDeletes += deleteRawContact(rawContactId, contactId, 3451fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 34522971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 34532971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 34542971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 34552971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 34562971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 34572971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 34582971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 34595ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 34602971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana final long rawContactId = ContentUris.parseId(uri); 3461fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return deleteRawContact(rawContactId, mDbHelper.getContactId(rawContactId), 3462fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov callerIsSyncAdapter); 3463508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3464508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 346520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 3466f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 3467944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong return deleteData(appendAccountToSelection(uri, selection), selectionArgs, 3468f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana callerIsSyncAdapter); 346920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 347020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 347148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 347248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 347348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 347448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3475508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 3476f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 34774da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(dataId); 34784da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov return deleteData(Data._ID + "=?", mSelectionArgs1, callerIsSyncAdapter); 3479ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3480ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3481ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3482f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 34835aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey return deleteGroup(uri, ContentUris.parseId(uri), callerIsSyncAdapter); 34842971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 34852971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana 34862971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana case GROUPS: { 34872971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana int numDeletes = 0; 34882971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups._ID}, 3489e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong appendAccountToSelection(uri, selection), selectionArgs, null, null, null); 34902971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana try { 34912971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana while (c.moveToNext()) { 34925aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey numDeletes += deleteGroup(uri, c.getLong(0), callerIsSyncAdapter); 34932971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 34942971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } finally { 34952971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana c.close(); 34962971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana } 349781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (numDeletes > 0) { 3498f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 349981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 35002971716e6a68660721d45be97bf3bd2dfad1c5efFred Quintana return numDeletes; 3501508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 3502508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 3503eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 350443880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3505e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey return deleteSettings(uri, appendAccountToSelection(uri, selection), selectionArgs); 3506eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3507eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 350882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 35090a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov return deleteStatusUpdates(selection, selectionArgs); 35101f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 35111f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 351281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 351381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 35143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 351581d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3516508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 35174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 35184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 35191c8e40c18f92722b9bec6e8ce2e345a9828efa16Dmitri Plotnikov public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) { 3520ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 3521b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final long groupMembershipMimetypeId = mDbHelper 352294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 3523de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov mDb.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 352494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 352594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana + groupId, null); 352694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 352794021b213e4db367f60b30fcbfe9019e28571784Fred Quintana try { 3528f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 3529de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 353094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } else { 353194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.clear(); 353294021b213e4db367f60b30fcbfe9019e28571784Fred Quintana mValues.put(Groups.DELETED, 1); 3533f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mValues.put(Groups.DIRTY, 1); 3534de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov return mDb.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId, null); 353594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 353694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } finally { 35371a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 353894021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 353994021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 354094021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 35415aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int deleteSettings(Uri uri, String selection, String[] selectionArgs) { 3542e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.delete(Tables.SETTINGS, selection, selectionArgs); 35431a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3544e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3545e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3546e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3547dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int deleteContact(long contactId, boolean callerIsSyncAdapter) { 354896b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(contactId); 3549cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov Cursor c = mDb.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, 355096b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker RawContacts.CONTACT_ID + "=?", mSelectionArgs1, 355196b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker null, null, null); 3552cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov try { 3553cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov while (c.moveToNext()) { 3554cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov long rawContactId = c.getLong(0); 3555dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 3556cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3557cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } finally { 3558cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov c.close(); 3559cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3560cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3561cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov return mDb.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 3562cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3563cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 3564fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) { 35653389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 3566f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (callerIsSyncAdapter) { 356714bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov mDb.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null); 3568fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov int count = mDb.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 3569fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov mContactAggregator.updateDisplayNameForContact(mDb, contactId); 3570fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return count; 357133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 3572b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.removeContactIfSingleton(rawContactId); 3573dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return markRawContactAsDeleted(rawContactId, callerIsSyncAdapter); 357433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 357533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 357633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 35770a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private int deleteStatusUpdates(String selection, String[] selectionArgs) { 35789705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // delete from both tables: presence and status_updates 35799705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 35809705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (VERBOSE_LOGGING) { 35819705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori Log.v(TAG, "deleting data from status_updates for " + selection); 35829705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 35839705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mDb.delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection), 35849705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 35859705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mDb.delete(Tables.PRESENCE, selection, selectionArgs); 35860a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 35870a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 3588dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int markRawContactAsDeleted(long rawContactId, boolean callerIsSyncAdapter) { 358981d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 359081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov 3591cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.clear(); 3592cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DELETED, 1); 3593cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 3594cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1); 3595cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 3596cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 3597dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana return updateRawContact(rawContactId, mValues, callerIsSyncAdapter); 3598cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov } 3599cb144e1429596701603c016f4a078f6331e6481dDmitri Plotnikov 36004f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 3601de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov protected int updateInTransaction(Uri uri, ContentValues values, String selection, 3602de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov String[] selectionArgs) { 3603bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 3604b5a4add17815167d20a90645779df34cdf45280dFred Quintana Log.v(TAG, "updateInTransaction: " + uri); 3605b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3606b5a4add17815167d20a90645779df34cdf45280dFred Quintana 360735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 360800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 360900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 3610b5a4add17815167d20a90645779df34cdf45280dFred Quintana if (match == SYNCSTATE_ID && selection == null) { 3611b5a4add17815167d20a90645779df34cdf45280dFred Quintana long rowId = ContentUris.parseId(uri); 36121129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov Object data = values.get(ContactsContract.SyncState.DATA); 3613b5a4add17815167d20a90645779df34cdf45280dFred Quintana mUpdatedSyncStates.put(rowId, data); 3614b5a4add17815167d20a90645779df34cdf45280dFred Quintana return 1; 3615b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 3616b5a4add17815167d20a90645779df34cdf45280dFred Quintana flushTransactionalChanges(); 3617f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana final boolean callerIsSyncAdapter = 3618f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); 361900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 362035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 3621b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 3622b5a4add17815167d20a90645779df34cdf45280dFred Quintana appendAccountToSelection(uri, selection), selectionArgs); 3623b5a4add17815167d20a90645779df34cdf45280dFred Quintana 3624b5a4add17815167d20a90645779df34cdf45280dFred Quintana case SYNCSTATE_ID: { 3625b5a4add17815167d20a90645779df34cdf45280dFred Quintana selection = appendAccountToSelection(uri, selection); 3626b5a4add17815167d20a90645779df34cdf45280dFred Quintana String selectionWithId = 3627b5a4add17815167d20a90645779df34cdf45280dFred Quintana (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ") 3628b5a4add17815167d20a90645779df34cdf45280dFred Quintana + (selection == null ? "" : " AND (" + selection + ")"); 3629b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().update(mDb, values, 3630b5a4add17815167d20a90645779df34cdf45280dFred Quintana selectionWithId, selectionArgs); 3631b5a4add17815167d20a90645779df34cdf45280dFred Quintana } 363235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 3633d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 3634dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(values, selection, selectionArgs, callerIsSyncAdapter); 363500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 363600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 363700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3638d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 3639dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(ContentUris.parseId(uri), values, callerIsSyncAdapter); 3640c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 3641c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 3642c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 36432e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP: 36442e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey case CONTACTS_LOOKUP_ID: { 36452e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final List<String> pathSegments = uri.getPathSegments(); 36462e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final int segmentCount = pathSegments.size(); 36472e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey if (segmentCount < 3) { 3648fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 3649fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 36502e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 36512e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final String lookupKey = pathSegments.get(2); 36522e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey final long contactId = lookupContactIdByLookupKey(mDb, lookupKey); 3653dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateContactOptions(contactId, values, callerIsSyncAdapter); 36542e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey break; 36552e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey } 36562e990cc352353b2e4d83f1eeecff137b94b84266Jeff Sharkey 36577d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh case RAW_CONTACTS_DATA: { 36587d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh final String rawContactId = uri.getPathSegments().get(1); 36597d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh String selectionWithId = (Data.RAW_CONTACT_ID + "=" + rawContactId + " ") 36607d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh + (selection == null ? "" : " AND " + selection); 36617d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 36627d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh count = updateData(uri, values, selectionWithId, selectionArgs, callerIsSyncAdapter); 36637d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 36647d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh break; 36657d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh } 36667d9fdcf8346f789436148eff1f00e8f49b370ef0Neel Parekh 366720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 3668944abb09aa47fc08db668be8909fc4045a681117Cynthia Wong count = updateData(uri, values, appendAccountToSelection(uri, selection), 3669f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 367081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3671f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 367281d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 367320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 367420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 3675c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 367648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case DATA_ID: 367748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 367848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 367948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 3680f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count = updateData(uri, values, selection, selectionArgs, callerIsSyncAdapter); 368181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3682f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 368381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 368400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 368500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 36867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 36875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 36885ac5c70d1165309302ebcc931f51723e37d31e0bJeff Sharkey selection = appendAccountToSelection(uri, selection); 3689dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, selection, selectionArgs, callerIsSyncAdapter); 36907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 36917e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 36927e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 36935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 369433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 36954529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (selection != null) { 36964da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 36974da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov count = updateRawContacts(values, RawContacts._ID + "=?" 3698dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana + " AND(" + selection + ")", selectionArgs, 3699dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 37004529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } else { 37014da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(rawContactId); 3702dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana count = updateRawContacts(values, RawContacts._ID + "=?", mSelectionArgs1, 3703dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana callerIsSyncAdapter); 37044529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 37057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 37067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 37077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 3708ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 37095aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, appendAccountToSelection(uri, selection), 3710f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana selectionArgs, callerIsSyncAdapter); 371181d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3712f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 371381d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3714ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3715ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3716ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3717ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 3718ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 37194da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(groupId)); 37204da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String selectionWithId = Groups._ID + "=? " 372173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov + (selection == null ? "" : " AND " + selection); 37225aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey count = updateGroups(uri, values, selectionWithId, selectionArgs, 37235aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey callerIsSyncAdapter); 372481d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov if (count > 0) { 3725f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana mSyncToNetwork |= !callerIsSyncAdapter; 372681d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 3727ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 3728ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 3729ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 3730127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 3731de955f25491cdc0e826ea5c7d4cd0e93cb970fb7Dmitri Plotnikov count = updateAggregationException(mDb, values); 3732b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 3733b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 3734b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3735eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 3736e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey count = updateSettings(uri, values, appendAccountToSelection(uri, selection), 3737e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey selectionArgs); 373843880c9228332d0ea1426341fcf712d302b2c55bDmitri Plotnikov mSyncToNetwork |= !callerIsSyncAdapter; 3739eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 3740eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 3741eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 37429705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori case STATUS_UPDATES: { 37439705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori count = updateStatusUpdate(uri, values, selection, selectionArgs); 37449705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori break; 37459705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 37469705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 374781d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov default: { 374881d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov mSyncToNetwork = true; 3749f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 375081d6a78dffd57f24f9aaecb6cd54e4084c3c9846Dmitri Plotnikov } 375100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 375200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 375300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 37544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 37554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 37569705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private int updateStatusUpdate(Uri uri, ContentValues values, String selection, 37579705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori String[] selectionArgs) { 37589705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // update status_updates table, if status is provided 37599705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO should account type/name be appended to the where clause? 37609705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori int updateCount = 0; 37619705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values); 37629705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 37639705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.STATUS_UPDATES, 37649705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues, 37659705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori getWhereClauseForStatusUpdatesTable(selection), 37669705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selectionArgs); 37679705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 37689705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 37699705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // now update the Presence table 37709705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori settableValues = getSettableColumnsForPresenceTable(values); 37719705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori if (settableValues.size() > 0) { 37729705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori updateCount = mDb.update(Tables.PRESENCE, settableValues, 37739705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori selection, selectionArgs); 37749705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 37759705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // TODO updateCount is not entirely a valid count of updated rows because 2 tables could 37769705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori // potentially get updated in this method. 37779705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return updateCount; 37789705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 37799705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 37809705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori /** 37819705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori * Build a where clause to select the rows to be updated in status_updates table. 37829705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori */ 37839705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private String getWhereClauseForStatusUpdatesTable(String selection) { 37849705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.setLength(0); 37859705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(WHERE_CLAUSE_FOR_STATUS_UPDATES_TABLE); 37869705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(selection); 37879705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mSb.append(")"); 37889705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mSb.toString(); 37899705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 37909705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 37919705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForStatusUpdatesTable(ContentValues values) { 37929705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 37939705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS, values, 37949705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS); 37959705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_TIMESTAMP, values, 37969705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_TIMESTAMP); 37979705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_RES_PACKAGE, values, 37989705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_RES_PACKAGE); 37999705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_LABEL, values, 38009705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_LABEL); 38019705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.STATUS_ICON, values, 38029705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.STATUS_ICON); 38039705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 38049705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 38059705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 38069705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori private ContentValues getSettableColumnsForPresenceTable(ContentValues values) { 38079705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori mValues.clear(); 38089705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori ContactsDatabaseHelper.copyStringValue(mValues, StatusUpdates.PRESENCE, values, 38099705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori StatusUpdates.PRESENCE); 38109705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori return mValues; 38119705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori } 38129705f5bcb04c4b3012a762fb3ba8620b518587ccVasu Nori 38135aec18c7ba70a011ffff949cfa3faaffce0a79c7Jeff Sharkey private int updateGroups(Uri uri, ContentValues values, String selectionWithId, 3814f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 381573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3816ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mGroupIdCache.clear(); 3817ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov 381873776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov ContentValues updatedValues; 3819f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana if (!callerIsSyncAdapter && !values.containsKey(Groups.DIRTY)) { 382073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = mValues; 382173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.clear(); 382273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.putAll(values); 382373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues.put(Groups.DIRTY, 1); 382473776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } else { 382573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov updatedValues = values; 382673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 382773776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 3828ac004680e3cc127b6ebf32b78d2813654b9c56fbJeff Sharkey int count = mDb.update(Tables.GROUPS, updatedValues, selectionWithId, selectionArgs); 38291a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (updatedValues.containsKey(Groups.GROUP_VISIBLE)) { 38301a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 383194021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 38326ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if (updatedValues.containsKey(Groups.SHOULD_SYNC) 38331129311abb3db9bf6eb5731da054276164e0b8d1Dmitri Plotnikov && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { 38346ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, 3835e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey Groups.ACCOUNT_TYPE}, selectionWithId, selectionArgs, null, 38366ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi null, null); 38376ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountName; 38386ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi String accountType; 38396ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi try { 38406ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi while (c.moveToNext()) { 38416ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountName = c.getString(0); 38426ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi accountType = c.getString(1); 38436ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi if(!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 38446ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi Account account = new Account(accountName, accountType); 3845ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov ContentResolver.requestSync(account, ContactsContract.AUTHORITY, 38466ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi new Bundle()); 38476ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi break; 38486ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 38496ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 38506ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } finally { 38516ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi c.close(); 38526ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 38536ce24dc1d53f1ed2760a06cd60c705ebdf666f43Megha Joshi } 385494021b213e4db367f60b30fcbfe9019e28571784Fred Quintana return count; 385594021b213e4db367f60b30fcbfe9019e28571784Fred Quintana } 385694021b213e4db367f60b30fcbfe9019e28571784Fred Quintana 3857b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private int updateSettings(Uri uri, ContentValues values, String selection, 3858b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov String[] selectionArgs) { 3859e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey final int count = mDb.update(Tables.SETTINGS, values, selection, selectionArgs); 38601a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey if (values.containsKey(Settings.UNGROUPED_VISIBLE)) { 38611a21fa6383449df4bf0d46138a23aa02dfa235a0Jeff Sharkey mVisibleTouched = true; 3862e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3863e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey return count; 3864e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 3865e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 3866dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContacts(ContentValues values, String selection, String[] selectionArgs, 3867dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 38684529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov if (values.containsKey(RawContacts.CONTACT_ID)) { 38694529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov throw new IllegalArgumentException(RawContacts.CONTACT_ID + " should not be included " + 38704529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov "in content values. Contact IDs are assigned automatically"); 38714529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 387273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 38734529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov int count = 0; 3874b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 387551bf5ea9531b9da72caff607dbdf35fd6f61cbe2Jeff Sharkey new String[] { RawContacts._ID }, selection, 38764529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov selectionArgs, null, null, null); 38774529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov try { 38784529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov while (cursor.moveToNext()) { 38794529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov long rawContactId = cursor.getLong(0); 3880dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateRawContact(rawContactId, values, callerIsSyncAdapter); 38814529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov count++; 38824529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 38834529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } finally { 38844529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov cursor.close(); 38854529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 38864529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 38874529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov return count; 38884529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov } 38894529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov 3890dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateRawContact(long rawContactId, ContentValues values, 3891dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 389296b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker final String selection = RawContacts._ID + " = ?"; 389396b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1[0] = Long.toString(rawContactId); 389419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka final boolean requestUndoDelete = (values.containsKey(RawContacts.DELETED) 389519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka && values.getAsInteger(RawContacts.DELETED) == 0); 389619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka int previousDeleted = 0; 3897ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountType = null; 3898ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov String accountName = null; 389919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete) { 390019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka Cursor cursor = mDb.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS, selection, 390196b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker mSelectionArgs1, null, null, null); 390219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka try { 390319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (cursor.moveToFirst()) { 390419cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka previousDeleted = cursor.getInt(RawContactsQuery.DELETED); 3905ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountType = cursor.getString(RawContactsQuery.ACCOUNT_TYPE); 3906ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov accountName = cursor.getString(RawContactsQuery.ACCOUNT_NAME); 390719cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 390819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } finally { 390919cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka cursor.close(); 391019cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 391119cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka values.put(ContactsContract.RawContacts.AGGREGATION_MODE, 391219cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT); 391319cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 3914f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 391596b7618a3996f2f356cb33553e76877d23a996f2Doug Zongker int count = mDb.update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1); 39165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count != 0) { 3917f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (values.containsKey(RawContacts.AGGREGATION_MODE)) { 3918f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov int aggregationMode = values.getAsInteger(RawContacts.AGGREGATION_MODE); 3919f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov 3920f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // As per ContactsContract documentation, changing aggregation mode 3921f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov // to DEFAULT should not trigger aggregation 3922f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov if (aggregationMode != RawContacts.AGGREGATION_MODE_DEFAULT) { 392369cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId, aggregationMode, false); 3924f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 3925f5a847e8c93db02f3334dbc276debd90bdea5658Dmitri Plotnikov } 3926433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey if (values.containsKey(RawContacts.STARRED)) { 3927dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter) { 3928dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 3929dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana values.getAsLong(RawContacts.STARRED) != 0); 3930dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 39314529f06d48c8ad3cc573a9b7b8f2f952b1e20dcdDmitri Plotnikov mContactAggregator.updateStarred(rawContactId); 3932dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } else { 3933dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then update the 3934dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // favorites group membership based on whether or not this contact is starred. 3935dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // If it is starred, add a group membership, if one doesn't already exist 3936dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // otherwise delete any matching group memberships. 3937dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 3938dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean starred = 0 != DatabaseUtils.longForQuery(mDb, 3939dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana SELECTION_STARRED_FROM_RAW_CONTACTS, 3940dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[]{Long.toString(rawContactId)}); 3941dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, starred); 3942dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3943dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 3944dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3945dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // if this raw contact is being associated with an account, then add a 3946dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana // group membership to the group marked as AutoAdd, if any. 3947dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!callerIsSyncAdapter && values.containsKey(RawContacts.ACCOUNT_NAME)) { 3948dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana addAutoAddMembership(rawContactId); 3949433a3a08a4726952c080e22e3969ac6c4f28e8dfJeff Sharkey } 3950dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 3951285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov if (values.containsKey(RawContacts.SOURCE_ID)) { 39522b7a632bba423357ae5641f94da6a2f71afc523bDmitri Plotnikov mContactAggregator.updateLookupKeyForRawContact(mDb, rawContactId); 3953285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov } 3954f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.containsKey(RawContacts.NAME_VERIFIED)) { 3955f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov 3956f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // If setting NAME_VERIFIED for this raw contact, reset it for all 3957f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov // other raw contacts in the same aggregate 3958f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov if (values.getAsInteger(RawContacts.NAME_VERIFIED) != 0) { 3959f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.bindLong(1, rawContactId); 3960f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.bindLong(2, rawContactId); 3961f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mResetNameVerifiedForOtherRawContacts.execute(); 3962f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 3963f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov mContactAggregator.updateDisplayNameForRawContact(mDb, rawContactId); 3964f01c876a92b9c950a0450ed8b706ac5eb2c9b660Dmitri Plotnikov } 396519cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka if (requestUndoDelete && previousDeleted == 1) { 396619cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka // undo delete, needs aggregation again. 3967ab91a8babdbda516d4e5088fedf3fdebf9cf88adDmitri Plotnikov mInsertedRawContacts.put(rawContactId, new Account(accountName, accountType)); 396819cf97e1f8a569ad782756183419b7ba45ce15a0Tadashi G. Takaoka } 39695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 39705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return count; 397133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 397233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 3973321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 3974f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 397520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 397620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 397720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 39785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 397920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 398020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 398120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 398220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 398320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 3984b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); 398520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 398620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 398770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 398870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 398920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 399020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 399120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 399270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 399320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 399470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 399520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 399670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 399720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 399870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 399920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 400020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4001653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov int count = 0; 400220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4003653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 4004653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov // so we don't need to worry about updating data we don't have permission to read. 400514bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov Cursor c = query(uri, DataUpdateQuery.COLUMNS, selection, selectionArgs, null); 4006653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov try { 4007653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov while(c.moveToNext()) { 4008f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana count += updateData(mValues, c, callerIsSyncAdapter); 400920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 4010653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov } finally { 4011653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov c.close(); 401220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 401320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4014653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return count; 401520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 401620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 4017f6be85f72615168c836b05c03ab5fc80d4794a82Fred Quintana private int updateData(ContentValues values, Cursor c, boolean callerIsSyncAdapter) { 4018653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov if (values.size() == 0) { 4019653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov return 0; 4020321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 4021653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov 402214bba94bbe0f2e215ad7b3b9417754a1ba0d95bfDmitri Plotnikov final String mimeType = c.getString(DataUpdateQuery.MIMETYPE); 4023a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov DataRowHandler rowHandler = getDataRowHandler(mimeType); 4024813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov if (rowHandler.update(mDb, values, c, callerIsSyncAdapter)) { 4025813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return 1; 4026813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov } else { 4027813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return 0; 4028a6733943584294492aa0118fc32bf4e58dabb028Dmitri Plotnikov } 4029321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 4030321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 40318c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov private int updateContactOptions(ContentValues values, String selection, 4032dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana String[] selectionArgs, boolean callerIsSyncAdapter) { 40338c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov int count = 0; 4034b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov Cursor cursor = mDb.query(mDbHelper.getContactView(), 40358c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov new String[] { Contacts._ID }, selection, 40368c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov selectionArgs, null, null, null); 40378c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov try { 40388c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov while (cursor.moveToNext()) { 40398c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov long contactId = cursor.getLong(0); 4040dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateContactOptions(contactId, values, callerIsSyncAdapter); 40418c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov count++; 40428c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 40438c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } finally { 40448c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov cursor.close(); 40458c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 40468c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 40478c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov return count; 40488c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov } 40498c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 4050dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private int updateContactOptions(long contactId, ContentValues values, 4051dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana boolean callerIsSyncAdapter) { 4052d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 40538c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 4054b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 4055d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 4056b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 4057d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 4058b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 4059d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 4060b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 4061d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 4062b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 4063d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 4064d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 4065d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 40668c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.size() == 0) { 4067d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 4068d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 4069d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 40708c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov if (mValues.containsKey(RawContacts.STARRED)) { 4071c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey // Mark dirty when changing starred to trigger sync 40728c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.put(RawContacts.DIRTY, 1); 4073c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey } 4074c76d0a78fe2d3471195cfa555bab016eec154f07Jeff Sharkey 40754da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs1[0] = String.valueOf(contactId); 40764da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mDb.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?", mSelectionArgs1); 40778c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 4078dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (mValues.containsKey(RawContacts.STARRED) && !callerIsSyncAdapter) { 4079dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana Cursor cursor = mDb.query(mDbHelper.getRawContactView(), 4080dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana new String[] { RawContacts._ID }, RawContacts.CONTACT_ID + "=?", 4081dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mSelectionArgs1, null, null, null); 4082dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana try { 4083dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana while (cursor.moveToNext()) { 4084dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana long rawContactId = cursor.getLong(0); 4085dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana updateFavoritesMembership(rawContactId, 4086dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana mValues.getAsLong(RawContacts.STARRED) != 0); 4087dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4088dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } finally { 4089dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana cursor.close(); 4090dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4091dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana } 4092dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana 40938c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // Copy changeable values to prevent automatically managed fields from 40948c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov // being explicitly updated by clients. 40958c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov mValues.clear(); 4096b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 40978c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 4098b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 40998c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 4100b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 41018c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 4102b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 41038c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 4104b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED, 41058c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov values, Contacts.STARRED); 41068c4f838f899daadb6f46f8c27ab7636023e39c38Dmitri Plotnikov 41079b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori int rslt = mDb.update(Tables.CONTACTS, mValues, Contacts._ID + "=?", mSelectionArgs1); 41086e38acbd1e72c62a6f8917297aed97e35c0c4697Vasu Nori 41099b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori if (values.containsKey(Contacts.LAST_TIME_CONTACTED) && 41109b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori !values.containsKey(Contacts.TIMES_CONTACTED)) { 41119b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1); 41129b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori mDb.execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1); 41139b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori } 41149b1bd62417ef1764829398a61c3d5df93a924106Vasu Nori return rslt; 4115f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 4116d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 4117127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 4118127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 41190c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId1 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID1); 41200c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rcId2 = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID2); 412180c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 41220c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov long rawContactId1, rawContactId2; 41230c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (rcId1 < rcId2) { 41240c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId1; 41250c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId2; 41260c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 41270c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId2 = rcId1; 41280c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov rawContactId1 = rcId2; 4129b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4130127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 41310c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 41324da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[0] = String.valueOf(rawContactId1); 41334da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov mSelectionArgs2[1] = String.valueOf(rawContactId2); 41340c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, 41354da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov AggregationExceptions.RAW_CONTACT_ID1 + "=? AND " 41364da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + AggregationExceptions.RAW_CONTACT_ID2 + "=?", mSelectionArgs2); 41370c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov } else { 41386bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 41396bc46c9f22aaa9e68f344b171426fc686d3b536aDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 41400c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1); 41410c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2); 41420c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 41430c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov exceptionValues); 4144127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 4145127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 41463389f7c7df6c90e48fcb0c27832bc322e5b20bf6Dmitri Plotnikov mContactAggregator.invalidateAggregationExceptionCache(); 414769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId1, 414869cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 414969cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov mContactAggregator.markForAggregation(rawContactId2, 415069cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DEFAULT, true); 4151dea3ee5e7f84be2abfe35837a460cbe779d319dbDmitri Plotnikov 4152b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId1 = mDbHelper.getContactId(rawContactId1); 41530c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId1, contactId1); 41540c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov 4155b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov long contactId2 = mDbHelper.getContactId(rawContactId2); 41560c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId2, contactId2); 4157127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 4158127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 4159127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 4160127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 4161b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4162b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 416370d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong public void onAccountsUpdated(Account[] accounts) { 4164f8536aaa7a52b9a7a353bc54e158becdbe79ec87Bai Tao // TODO : Check the unit test. 4165627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> existingAccounts = new HashSet<Account>(); 416670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.beginTransaction(); 416770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong try { 4168dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana findValidAccounts(existingAccounts); 4169743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov 4170743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov // Add a row to the ACCOUNTS table for each new account 4171743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov for (Account account : accounts) { 4172743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov if (!existingAccounts.contains(account)) { 4173743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov mDb.execSQL("INSERT INTO " + Tables.ACCOUNTS + " (" + RawContacts.ACCOUNT_NAME 4174743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov + ", " + RawContacts.ACCOUNT_TYPE + ") VALUES (?, ?)", 4175743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov new String[] {account.name, account.type}); 4176743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 4177743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov } 417848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 4179627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov // Remove all valid accounts from the existing account set. What is left 4180743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov // in the accountsToDelete set will be extra accounts whose data must be deleted. 4181627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov HashSet<Account> accountsToDelete = new HashSet<Account>(existingAccounts); 4182627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (Account account : accounts) { 4183627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov accountsToDelete.remove(account); 418470d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 418570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong 418670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong for (Account account : accountsToDelete) { 41875f9e610be459bd1332e182c41cf7510265d5f7ccFred Quintana Log.d(TAG, "removing data for removed account " + account); 4188627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov String[] params = new String[] {account.name, account.type}; 4189627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 4190627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.GROUPS + 4191627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Groups.ACCOUNT_NAME + " = ?" + 4192627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Groups.ACCOUNT_TYPE + " = ?", params); 4193627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 4194627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.PRESENCE + 4195627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + 4196627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "SELECT " + RawContacts._ID + 4197627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 4198627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 4199627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?)", params); 4200627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 4201627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.RAW_CONTACTS + 4202627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + 4203627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + " = ?", params); 4204627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov mDb.execSQL( 4205627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov "DELETE FROM " + Tables.SETTINGS + 4206627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " WHERE " + Settings.ACCOUNT_NAME + " = ?" + 4207627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov " AND " + Settings.ACCOUNT_TYPE + " = ?", params); 4208743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov mDb.execSQL( 4209743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov "DELETE FROM " + Tables.ACCOUNTS + 4210743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " WHERE " + RawContacts.ACCOUNT_NAME + "=?" + 4211743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " AND " + RawContacts.ACCOUNT_TYPE + "=?", params); 4212627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4213627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 421433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov if (!accountsToDelete.isEmpty()) { 421533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // Find all aggregated contacts that used to contain the raw contacts 421633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // we have just deleted and see if they are still referencing the deleted 421733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov // names of photos. If so, fix up those contacts. 421833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov HashSet<Long> orphanContactIds = Sets.newHashSet(); 421933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Cursor cursor = mDb.rawQuery("SELECT " + Contacts._ID + 422033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " FROM " + Tables.CONTACTS + 422133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " WHERE (" + Contacts.NAME_RAW_CONTACT_ID + " NOT NULL AND " + 422269cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov Contacts.NAME_RAW_CONTACT_ID + " NOT IN " + 422369cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + RawContacts._ID + 422469cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + "))" + 422533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov " OR (" + Contacts.PHOTO_ID + " NOT NULL AND " + 422633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov Contacts.PHOTO_ID + " NOT IN " + 422769cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov "(SELECT " + Data._ID + 422869cc3a2b09e2ffb606c6e52a71b604bba526d225Dmitri Plotnikov " FROM " + Tables.DATA + "))", null); 422933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov try { 423033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov while (cursor.moveToNext()) { 423133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov orphanContactIds.add(cursor.getLong(0)); 423233fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 423333fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } finally { 423433fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov cursor.close(); 423533fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 423633fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 423733fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov for (Long contactId : orphanContactIds) { 423833fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 423933fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 424033fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov } 424133fd566fb6eebdd40a900c0c8a2f6dca894d7829Dmitri Plotnikov 4242609cc5b4c96a6981f675a70ff743ecfec2b448e6Daniel Lehmann mDbHelper.updateAllVisible(); 4243609cc5b4c96a6981f675a70ff743ecfec2b448e6Daniel Lehmann 4244b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.getSyncState().onAccountsChanged(mDb, accounts); 424570d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.setTransactionSuccessful(); 424670d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } finally { 424770d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong mDb.endTransaction(); 424870d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 424973f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.clear(); 425070d2ff8c87961703351b223ce8b15342fe795a0bCynthia Wong } 4251619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4252619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 4253627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov * Finds all distinct accounts present in the specified table. 4254627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov */ 4255dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana private void findValidAccounts(Set<Account> validAccounts) { 4256743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov Cursor c = mDb.rawQuery( 4257743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov "SELECT " + RawContacts.ACCOUNT_NAME + "," + RawContacts.ACCOUNT_TYPE + 4258743eac356404195f236ad44379fe9d180beb5bf2Dmitri Plotnikov " FROM " + Tables.ACCOUNTS, null); 4259627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 4260627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov while (c.moveToNext()) { 4261dd5c25c65f09ada246c826fb6d04f0b6d4cf4388Fred Quintana if (!c.isNull(0) || !c.isNull(1)) { 4262627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov validAccounts.add(new Account(c.getString(0), c.getString(1))); 4263627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4264627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4265627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } finally { 4266627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov c.close(); 4267627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4268627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 4269627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov 4270627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov /** 4271622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey * Test all against {@link TextUtils#isEmpty(CharSequence)}. 4272622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey */ 427367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov private static boolean areAllEmpty(ContentValues values, String[] keys) { 427467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov for (String key : keys) { 427567c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov if (!TextUtils.isEmpty(values.getAsString(key))) { 427667c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return false; 427767c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 427867c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 427967c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov return true; 428067c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov } 428167c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov 428267c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov /** 428367c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov * Returns true if a value (possibly null) is specified for at least one of the supplied keys. 428467c9ed1cefa5c084d3f373d7f1ecb7122983ff15Dmitri Plotnikov */ 4285dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov private static boolean areAnySpecified(ContentValues values, String[] keys) { 4286622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey for (String key : keys) { 4287dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov if (values.containsKey(key)) { 4288dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return true; 4289622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 4290622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 4291dd0e0f44fe403ff201d46d5534f7f1148e5ad729Dmitri Plotnikov return false; 4292622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey } 4293622e0a2f00b3de248926ec9e89b11a6425919819Jeff Sharkey 42944f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 42954f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 42964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 4297bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov if (VERBOSE_LOGGING) { 4298bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov Log.v(TAG, "query: " + uri); 4299bce6ee29f2d971ceae2bfce85a06bb3ecec6537aDmitri Plotnikov } 43000b30cac29514b3978896731ba1df6a54fc94e9e4Dmitri Plotnikov 4301b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 430235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4303d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 43041f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 4305c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 4306c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4307619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 4308619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 4309a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 43104f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 431135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 4312b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getSyncState().query(db, projection, selection, selectionArgs, 431335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 431435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 4315d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 4316763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 4317619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 4318619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 4319619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 4320d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 43214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 4322763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 43234da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 43244da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 43256bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 43266bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 43276bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 43285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP: 43295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov case CONTACTS_LOOKUP_ID: { 43305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 43315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = pathSegments.size(); 43325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount < 3) { 4333fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 4334fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Missing a lookup key", uri)); 43355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String lookupKey = pathSegments.get(2); 43375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segmentCount == 4) { 43382d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill // TODO: pull this out into a method and generalize to not require contactId 43395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = Long.parseLong(pathSegments.get(3)); 43405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder(); 4341763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(lookupQb, uri, projection); 43424da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String[] args; 43434da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov if (selectionArgs == null) { 43444da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args = new String[2]; 43454da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } else { 43464da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args = new String[selectionArgs.length + 2]; 43474da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov System.arraycopy(selectionArgs, 0, args, 2, selectionArgs.length); 43484da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov } 43494da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov args[0] = String.valueOf(contactId); 435060de6f6c3c70e53b603a47b0efc80993353a8368Daniel Lehmann args[1] = Uri.encode(lookupKey); 43514da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?"); 43524da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov Cursor c = query(db, lookupQb, projection, selection, args, sortOrder, 43535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov groupBy, limit); 43545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (c.getCount() != 0) { 43555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return c; 43565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 43585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 43595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4361763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 43624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 43634da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 43644da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 43655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 43665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 43675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 4368f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 4369f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // When reading as vCard always use restricted view 437042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 4371763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(mDbHelper.getContactView(true /* require restricted */)); 4372f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey qb.setProjectionMap(sContactsVCardProjectionMap); 43734da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, 43744da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov String.valueOf(lookupContactIdByLookupKey(db, lookupKey))); 43754da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Contacts._ID + "=?"); 4376f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey break; 4377f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey } 4378f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey 437942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 438042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); 438142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann String currentDateString = dateFormat.format(new Date()).toString(); 438242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann return db.rawQuery( 438342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann "SELECT" + 438442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " 'vcards_' || ? || '.vcf' AS " + OpenableColumns.DISPLAY_NAME + "," + 438542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann " NULL AS " + OpenableColumns.SIZE, 438642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann new String[] { currentDateString }); 438742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 438842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 4389ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_FILTER: { 4390916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String filterParam = ""; 4391ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 4392916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov filterParam = uri.getLastPathSegment(); 4393ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4394916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov setTablesAndProjectionMapForContactsWithSnippet(qb, uri, projection, filterParam); 4395ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4396ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4397ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 4398ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT_FILTER: 4399ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_STREQUENT: { 44004a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterSql = null; 4401ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov if (match == CONTACTS_STREQUENT_FILTER 4402d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 44034a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 44044a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 4405e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(Contacts._ID + " IN "); 44065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov appendContactFilterAsNestedQuery(sb, filterParam); 44074a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov filterSql = sb.toString(); 44084a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 44094a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4410763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 4411ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 44125e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] starredProjection = null; 44135e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] frequentProjection = null; 44145e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection != null) { 44155e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar starredProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 44165e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar frequentProjection = appendProjectionArg(projection, TIMES_CONTACED_SORT_COLUMN); 44175e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 44185e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 44194a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov // Build the first query for starred 44204a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 44214a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 4422d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 44235e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentStarredProjectionMap); 44245e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String starredQuery = qb.buildQuery(starredProjection, Contacts.STARRED + "=1", 44254a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 4426d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 4427d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 4428d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 4429763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 44304a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (filterSql != null) { 44314a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(filterSql); 4432d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 44335e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar qb.setProjectionMap(sStrequentFrequentProjectionMap); 44345e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final String frequentQuery = qb.buildQuery(frequentProjection, 4435d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 4436d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 44374a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov null, Contacts._ID, null, null, null); 4438d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 4439d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 4440d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 4441d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 44424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov Cursor c = db.rawQuery(query, null); 44434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (c != null) { 4444d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 4445d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 4446d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 4447d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 4448d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 4449d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 4450ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_GROUP: { 4451763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 4452b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 445371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 44544a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 4455b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4456b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 4457b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 4458b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 4459d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_DATA: { 44604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 446182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 44624da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 44634da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 44646bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 44656bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 446600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 4467ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov case CONTACTS_PHOTO: { 44683653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 446982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 44704da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId)); 44714da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts.CONTACT_ID + "=?"); 44723653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID); 44733653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov break; 44743653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov } 44753653cf1fa8fb36a96a7e4a6ebd615438877c3183Dmitri Plotnikov 44764a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case PHONES: { 447782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 447889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 44792815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 44802815f58f72f109790585931f601a63ddc02536a5Evan Millar } 44812815f58f72f109790585931f601a63ddc02536a5Evan Millar 448248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: { 448382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 44844da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 448548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 44864da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 448748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 448848828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 448948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 4490ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 449182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 449289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 4493ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 44944a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov String filterParam = uri.getLastPathSegment(); 44954a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 4496a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov sb.append(" AND ("); 44975e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 449845d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov boolean hasCondition = false; 44995e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov boolean orNeeded = false; 45005e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 45015e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (normalizedName.length() > 0) { 45025e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data.RAW_CONTACT_ID + " IN "); 45037318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 45045e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov orNeeded = true; 450545d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 45065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 45075e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 45085e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (isPhoneNumber(filterParam)) { 45095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if (orNeeded) { 45105e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(" OR "); 45115e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 45125e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String number = PhoneNumberUtils.convertKeypadLettersToDigits(filterParam); 45135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov String reversed = PhoneNumberUtils.getStrippedReversed(number); 45145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(Data._ID + 45155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov " IN (SELECT " + PhoneLookupColumns.DATA_ID 45165e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " FROM " + Tables.PHONE_LOOKUP 45175e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov + " WHERE " + PhoneLookupColumns.NORMALIZED_NUMBER + " LIKE '%"); 45185e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(reversed); 45195e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append("')"); 452045d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov hasCondition = true; 452145d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov } 452245d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov 452345d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov if (!hasCondition) { 452445d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // If it is neither a phone number nor a name, the query should return 452545d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov // an empty cursor. Let's ensure that. 452645d8626bf586b5c7111fa86324a7201ae8073607Dmitri Plotnikov sb.append("0"); 45275e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 45285e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 4529a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 4530ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 45315e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = PhoneColumns.NORMALIZED_NUMBER + "," + RawContacts.CONTACT_ID; 4532a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 4533a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 4534a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 4535ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4536ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4537ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 45384a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov case EMAILS: { 453982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 454089c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 45414a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov break; 45424a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 45434a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 454448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: { 454582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 45464da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 45474da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'" 45484da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov + " AND " + Data._ID + "=?"); 454948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 455048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 455148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 45525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_LOOKUP: { 455382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 455489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'"); 45554a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov if (uri.getPathSegments().size() > 2) { 455608768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String email = uri.getLastPathSegment(); 455708768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov String address = mDbHelper.extractAddressFromEmailAddress(email); 455808768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, address); 455908768a0f3434130fa46379c1bbfec93a19094939Dmitri Plotnikov qb.appendWhere(" AND UPPER(" + Email.DATA + ")=UPPER(?)"); 45604a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 4561ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4562ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4563ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 45645e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov case EMAILS_FILTER: { 456582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, true); 456607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov String filterParam = null; 456707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 456807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = uri.getLastPathSegment(); 456907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (TextUtils.isEmpty(filterParam)) { 457007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov filterParam = null; 457107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 457207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } 45735e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 457407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov if (filterParam == null) { 457507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov // If the filter is unspecified, return nothing 457607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov qb.appendWhere(" AND 0"); 457707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov } else { 457807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov StringBuilder sb = new StringBuilder(); 457907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append(" AND " + Data._ID + " IN ("); 458007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 458107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov "SELECT " + Data._ID + 458207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 458307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " WHERE " + DataColumns.MIMETYPE_ID + "=" + mMimeTypeIdEmail + 458407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " AND " + Data.DATA1 + " LIKE "); 458507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, filterParam + '%'); 458620938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (!filterParam.contains("@")) { 458720938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov String normalizedName = NameNormalizer.normalize(filterParam); 458820938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (normalizedName.length() > 0) { 458907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov 459007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov /* 459107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * Using a UNION instead of an "OR" to make SQLite use the right 459207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * indexes. We need it to use the (mimetype,data1) index for the 459307ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * email lookup (see above), but not for the name lookup. 459407ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * SQLite is not smart enough to use the index on one side of an OR 459507ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * but not on the other. Using two separate nested queries 459607ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov * and a UNION between them does the job. 459707ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov */ 459807ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov sb.append( 459907ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " UNION SELECT " + Data._ID + 460007ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " FROM " + Tables.DATA + 460107ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " WHERE +" + DataColumns.MIMETYPE_ID + "=" + mMimeTypeIdEmail + 460207ce1624de652aa8494630a071b051a1670c4e3dDmitri Plotnikov " AND " + Data.RAW_CONTACT_ID + " IN "); 46037318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, normalizedName, false); 460420938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 46055e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 46065e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(")"); 4607a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov qb.appendWhere(sb); 46085e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 46095e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov groupBy = Email.DATA + "," + RawContacts.CONTACT_ID; 4610a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov if (sortOrder == null) { 4611a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov sortOrder = Contacts.IN_VISIBLE_GROUP + " DESC, " + RawContacts.CONTACT_ID; 4612a0e72d9b20207ec244f92ace2917932990f2bc8bDmitri Plotnikov } 46135e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov break; 46145e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 46155e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 4616ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 461782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 461889c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 461989c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 4620ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 4621ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 4622ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 462348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: { 462482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 46254da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 462648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov qb.appendWhere(" AND " + Data.MIMETYPE + " = '" 462748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov + StructuredPostal.CONTENT_ITEM_TYPE + "'"); 46284da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 462948828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov break; 463048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov } 463148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov 46325ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 4633763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 46344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 46354f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 46364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 46375ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 46385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 4639763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForRawContacts(qb, uri); 46404da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 46414da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 46424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 46434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 46444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 46455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 46465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 464782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 46484da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 46494da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data.RAW_CONTACT_ID + "=?"); 4650e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 4651e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 4652e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 4653e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 465482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 4655e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 4656e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 4657e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 46584f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 465982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov setTablesAndProjectionMapForData(qb, uri, projection, false); 46604da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 46614da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + Data._ID + "=?"); 4662a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov break; 4663a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov } 4664a6def2055f5d12cb6ee5cc3dc1adaf39f2b7c97cDmitri Plotnikov 4665a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 46664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 4667a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 4668a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 4669a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 4670e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov sortOrder = RawContactsColumns.CONCRETE_ID; 4671a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 4672a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 4673e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov String number = uri.getPathSegments().size() > 1 ? uri.getLastPathSegment() : ""; 4674b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.buildPhoneLookupAndContactQuery(qb, number); 4675e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov qb.setProjectionMap(sPhoneLookupProjectionMap); 4676e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov 4677e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov // Phone lookup cannot be combined with a selection 4678e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selection = null; 4679e3eb7ef438010c893c429f3031dcc7298171865dDmitri Plotnikov selectionArgs = null; 4680a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 4681a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 4682a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 4683ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 4684b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 4685ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 468689c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 4687ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4688ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4689ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4690ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 4691b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView()); 4692ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 46934da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 46944da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(Groups._ID + "=?"); 4695ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4696ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4697ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4698ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 4699b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getGroupView() + " AS groups"); 4700ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 470189c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 470289c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov groupBy = Groups._ID; 4703ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 4704ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 4705ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 4706b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 47070c0adda32be5de3acf392ab715cff468b6b340f8Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS); 4708b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 4709b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 4710b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 4711b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 471231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 4713d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 47142d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov String filter = null; 47152d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov if (uri.getPathSegments().size() > 3) { 47162d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov filter = uri.getPathSegments().get(3); 47172d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov } 471831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 4719d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov if (limit != null) { 4720d659078547c329b58f90d8809910a845d913dbc6Dmitri Plotnikov maxSuggestions = Integer.parseInt(limit); 472131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 472231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 472331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 472431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 4725763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar setTablesAndProjectionMapForContacts(qb, uri, projection); 47267581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov 47277581213e160c460671aebdb054b8afd2f138d99eDmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(qb, projection, contactId, 47282d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov maxSuggestions, filter); 472931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 473031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 4731eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey case SETTINGS: { 4732eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setTables(Tables.SETTINGS); 4733eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey qb.setProjectionMap(sSettingsProjectionMap); 473489c626eb655440c86a2e5df076e83708c1b32c17Dmitri Plotnikov appendAccountFromParameter(qb, uri); 4735e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4736e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // When requesting specific columns, this query requires 4737e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey // late-binding of the GroupMembership MIME-type. 4738b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final String groupMembershipMimetypeId = Long.toString(mDbHelper 4739e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)); 474082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 4741b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_COUNT)) { 4742e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 4743e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 474482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov if (projection != null && projection.length != 0 && 4745b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper.isInProjection(projection, Settings.UNGROUPED_WITH_PHONES)) { 4746e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey selectionArgs = insertSelectionArg(selectionArgs, groupMembershipMimetypeId); 4747e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey } 4748e07913c61c320b0cc2036db3b714e39534d8cd7aJeff Sharkey 4749eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey break; 4750eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey } 4751eb9ffdccfa19f5b2f22e688f733fd77e39605f9eJeff Sharkey 475282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES: { 47530a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 47545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 47555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 47565ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 475782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov case STATUS_UPDATES_ID: { 47580a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov setTableAndProjectionMapForStatusUpdates(qb, projection); 47594da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 47604da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(DataColumns.CONCRETE_ID + "=?"); 47615ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 47625ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 47635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 4764c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 4765a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 4766c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4767c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 4768c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 47692d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill String lookupKey = uri.getLastPathSegment(); 47702d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill return mGlobalSearchSupport.handleSearchShortcutRefresh(db, lookupKey, projection); 4771c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 4772c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 47731b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS: 4774b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 47751b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 47761b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 47771b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 47781b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_WITH_PHONES: 4779b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 47801b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 47811b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.HAS_PHONE_NUMBER + "=1"); 47821b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 47831b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 47841b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_FAVORITES: 4785b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 47861b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 47871b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.appendWhere(Contacts.STARRED + "=1"); 47881b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 47891b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 47901b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov case LIVE_FOLDERS_CONTACTS_GROUP_NAME: 4791b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov qb.setTables(mDbHelper.getContactView()); 47921b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov qb.setProjectionMap(sLiveFoldersProjectionMap); 479371e051c79a57af70ec7b095074c3e7faf9507b52Dmitri Plotnikov qb.appendWhere(CONTACTS_IN_GROUP_SELECT); 47941b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment()); 47951b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov break; 47961b7a7947242bb3b8caaed871775e62d486144c9fDmitri Plotnikov 479746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITIES: { 479846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 479946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 480046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 480146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 480246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana case RAW_CONTACT_ENTITY_ID: { 480346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 480446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana setTablesAndProjectionMapForRawContactsEntities(qb, uri); 48054da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(rawContactId)); 48064da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov qb.appendWhere(" AND " + RawContacts._ID + "=?"); 480746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana break; 480846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 480946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 481009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov case PROVIDER_STATUS: { 481109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return queryProviderStatus(uri, projection); 481209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 481309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 48144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 4815f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 4816c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 48174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 48184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 48197f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov qb.setStrictProjectionMap(true); 48207f786e5cbde9975b9632beb9b6d19eeef8a64cf1Dmitri Plotnikov 4821ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov Cursor cursor = 4822ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit); 4823ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (readBooleanQueryParameter(uri, ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, false)) { 4824ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov cursor = bundleLetterCountExtras(cursor, db, qb, selection, selectionArgs, sortOrder); 4825ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4826ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return cursor; 48275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 48285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 48295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 48305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String selection, String[] selectionArgs, String sortOrder, String groupBy, 48315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String limit) { 4832038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana if (projection != null && projection.length == 1 4833038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana && BaseColumns._COUNT.equals(projection[0])) { 4834038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana qb.setProjectionMap(sCountProjectionMap); 4835038c3db1b54dd9313c10c212025d37ca8a9e660fFred Quintana } 48365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, 48375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sortOrder, limit); 48384f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 48394f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 48404f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 48414f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 48424f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 48434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 484409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov /** 484509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov * Creates a single-row cursor containing the current status of the provider. 484609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov */ 484709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov private Cursor queryProviderStatus(Uri uri, String[] projection) { 484809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov MatrixCursor cursor = new MatrixCursor(projection); 484909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov RowBuilder row = cursor.newRow(); 485009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov for (int i = 0; i < projection.length; i++) { 485109c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov if (ProviderStatus.STATUS.equals(projection[i])) { 485209c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mProviderStatus); 485309c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } else if (ProviderStatus.DATA1.equals(projection[i])) { 485409c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov row.add(mEstimatedStorageRequirement); 485509c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 485609c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 485709c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov return cursor; 485809c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov } 485909c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 486009c6613dd14cb1911da5d62e39a4e54eb8f4666fDmitri Plotnikov 4861bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov private static final class AddressBookIndexQuery { 4862bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String LETTER = "letter"; 4863bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String TITLE = "title"; 4864bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String COUNT = "count"; 4865ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4866bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final String[] COLUMNS = new String[] { 4867bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov LETTER, TITLE, COUNT 4868ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 4869ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4870bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_LETTER = 0; 4871bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_TITLE = 1; 4872bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov public static final int COLUMN_COUNT = 2; 4873bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4874de8f19d5cc1ef7d5bd76ede6be888dad37112966Daisuke Miyakawa public static final String ORDER_BY = LETTER + " COLLATE " + PHONEBOOK_COLLATOR_NAME; 4875ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4876ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4877ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov /** 4878ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * Computes counts by the address book index titles and adds the resulting tally 4879ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov * to the returned cursor as a bundle of extras. 4880ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov */ 4881ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov private Cursor bundleLetterCountExtras(Cursor cursor, final SQLiteDatabase db, 4882ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov SQLiteQueryBuilder qb, String selection, String[] selectionArgs, String sortOrder) { 4883ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortKey; 4884ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4885ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // The sort order suffix could be something like "DESC". 4886ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // We want to preserve it in the query even though we will change 4887ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov // the sort column itself. 4888ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String sortOrderSuffix = ""; 4889ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (sortOrder != null) { 4890ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int spaceIndex = sortOrder.indexOf(' '); 4891ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov if (spaceIndex != -1) { 4892ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder.substring(0, spaceIndex); 4893ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortOrderSuffix = sortOrder.substring(spaceIndex); 4894ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 4895ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = sortOrder; 4896ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4897ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } else { 4898ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov sortKey = Contacts.SORT_KEY_PRIMARY; 4899ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4900ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4901bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String locale = getLocale().toString(); 4902ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov HashMap<String, String> projectionMap = Maps.newHashMap(); 4903bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov projectionMap.put(AddressBookIndexQuery.LETTER, 4904bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov "SUBSTR(" + sortKey + ",1,1) AS " + AddressBookIndexQuery.LETTER); 4905bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4906bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov /** 4907bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * Use the GET_PHONEBOOK_INDEX function, which is an android extension for SQLite3, 4908bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * to map the first letter of the sort key to a character that is traditionally 4909bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * used in phonebooks to represent that letter. For example, in Korean it will 4910bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * be the first consonant in the letter; for Japanese it will be Hiragana rather 4911bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov * than Katakana. 4912bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov */ 4913ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.TITLE, 4914bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov "GET_PHONEBOOK_INDEX(SUBSTR(" + sortKey + ",1,1),'" + locale + "')" 4915bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov + " AS " + AddressBookIndexQuery.TITLE); 4916ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov projectionMap.put(AddressBookIndexQuery.COUNT, 4917ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov "COUNT(" + Contacts._ID + ") AS " + AddressBookIndexQuery.COUNT); 4918ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov qb.setProjectionMap(projectionMap); 4919ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4920f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov Cursor indexCursor = qb.query(db, AddressBookIndexQuery.COLUMNS, selection, selectionArgs, 4921ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY, null /* having */, 4922ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov AddressBookIndexQuery.ORDER_BY + sortOrderSuffix); 4923ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4924ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov try { 4925f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov int groupCount = indexCursor.getCount(); 4926ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov String titles[] = new String[groupCount]; 4927ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov int counts[] = new int[groupCount]; 4928bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int indexCount = 0; 4929bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String currentTitle = null; 4930bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4931bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // Since GET_PHONEBOOK_INDEX is a many-to-1 function, we may end up 4932bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // with multiple entries for the same title. The following code 4933bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov // collapses those duplicates. 4934ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov for (int i = 0; i < groupCount; i++) { 4935f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.moveToNext(); 4936bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String title = indexCursor.getString(AddressBookIndexQuery.COLUMN_TITLE); 4937bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int count = indexCursor.getInt(AddressBookIndexQuery.COLUMN_COUNT); 4938bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount == 0 || !TextUtils.equals(title, currentTitle)) { 4939bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles[indexCount] = currentTitle = title; 4940bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount] = count; 4941bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov indexCount++; 4942bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } else { 4943bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts[indexCount - 1] += count; 4944bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4945bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov } 4946bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4947bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov if (indexCount < groupCount) { 4948bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov String[] newTitles = new String[indexCount]; 4949bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(titles, 0, newTitles, 0, indexCount); 4950bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov titles = newTitles; 4951bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov 4952bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov int[] newCounts = new int[indexCount]; 4953bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov System.arraycopy(counts, 0, newCounts, 0, indexCount); 4954bfd59cb11248659d12a379394774da8ff6f36cefDmitri Plotnikov counts = newCounts; 4955ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4956ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4957ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov final Bundle bundle = new Bundle(); 4958ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov bundle.putStringArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, titles); 4959f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov bundle.putIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS, counts); 4960ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return new CursorWrapper(cursor) { 4961ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 4962ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov @Override 4963ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov public Bundle getExtras() { 4964ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov return bundle; 4965ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4966ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov }; 4967ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } finally { 4968f3f4a385d8d1d6788ba79ca353d02235de1d9b33Dmitri Plotnikov indexCursor.close(); 4969ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4970ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov } 4971ba2c85b4700fbb3ecaf75e1101735f60b5483527Dmitri Plotnikov 49722d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill /** 497392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Returns the contact Id for the contact identified by the lookupKey. 497492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * Robust against changes in the lookup key: if the key has changed, will 497592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * look up the contact by the raw contact IDs or name encoded in the lookup 497692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov * key. 49772d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill */ 49782d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill public long lookupContactIdByLookupKey(SQLiteDatabase db, String lookupKey) { 49795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey key = new ContactLookupKey(); 49805870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments = key.parse(lookupKey); 49815870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 498292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov long contactId = -1; 498392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_SOURCE_ID)) { 498492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdBySourceIds(db, segments); 498592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 498692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 498792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 498892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 498992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 499092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov boolean hasRawContactIds = 499192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID); 499292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds) { 499392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov contactId = lookupContactIdByRawContactIds(db, segments); 499492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (contactId != -1) { 499592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return contactId; 499692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 499792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 499892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 499992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (hasRawContactIds 500092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || lookupKeyContainsType(segments, ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME)) { 50015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = lookupContactIdByDisplayNames(db, segments); 50025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 50045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 50055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 50075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private interface LookupBySourceIdQuery { 50085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 50095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 50105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 50115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 50125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 50135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 50145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.SOURCE_ID 50155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 50165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 50175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 50185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 50195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 50205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int SOURCE_ID = 3; 50215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 50235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long lookupContactIdBySourceIds(SQLiteDatabase db, 50245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ArrayList<LookupKeySegment> segments) { 50255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 50265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(RawContacts.SOURCE_ID + " IN ("); 50275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 50285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 502992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID) { 50305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 50315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 50325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 50355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 50365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 50375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupBySourceIdQuery.TABLE, LookupBySourceIdQuery.COLUMNS, 50385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 50395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 50405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 50415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupBySourceIdQuery.ACCOUNT_TYPE); 50425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupBySourceIdQuery.ACCOUNT_NAME); 50435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 50445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 50455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String sourceId = c.getString(LookupBySourceIdQuery.SOURCE_ID); 50465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 50475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 504892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_SOURCE_ID 504992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 50505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(sourceId)) { 50515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupBySourceIdQuery.CONTACT_ID); 50525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 50535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 50575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 50585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 50605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 50615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 506392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByRawContactIdQuery { 506492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.RAW_CONTACTS; 50655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 50665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String COLUMNS[] = { 50675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.CONTACT_ID, 50685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_TYPE, 50695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov RawContacts.ACCOUNT_NAME, 507092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts._ID, 50715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov }; 50725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 50735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int CONTACT_ID = 0; 50745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_TYPE = 1; 50755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int ACCOUNT_NAME = 2; 507692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ID = 3; 50775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50785870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 507992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByRawContactIds(SQLiteDatabase db, 508092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 508192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 508292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(RawContacts._ID + " IN ("); 50835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 50845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 508592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 508692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(segment.rawContactId); 508792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(","); 50885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 50895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 509092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 509192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.append(") AND " + RawContacts.CONTACT_ID + " NOT NULL"); 50925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 509392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov Cursor c = db.query(LookupByRawContactIdQuery.TABLE, LookupByRawContactIdQuery.COLUMNS, 509492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov sb.toString(), null, null, null, null); 509592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov try { 509692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov while (c.moveToNext()) { 509792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountType = c.getString(LookupByRawContactIdQuery.ACCOUNT_TYPE); 509892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String accountName = c.getString(LookupByRawContactIdQuery.ACCOUNT_NAME); 509992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int accountHashCode = 510092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 510192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String rawContactId = c.getString(LookupByRawContactIdQuery.ID); 510292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 510392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 510492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID 510592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 510692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && segment.rawContactId.equals(rawContactId)) { 510792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov segment.contactId = c.getLong(LookupByRawContactIdQuery.CONTACT_ID); 510892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov break; 510992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 511092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 511192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 511292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } finally { 511392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov c.close(); 51145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 511692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return getMostReferencedContactId(segments); 511792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 511892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 511992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private interface LookupByDisplayNameQuery { 512092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS; 512192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 512292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov String COLUMNS[] = { 512392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.CONTACT_ID, 512492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 512592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 512692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov NameLookupColumns.NORMALIZED_NAME 512792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov }; 512892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 512992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int CONTACT_ID = 0; 513092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_TYPE = 1; 513192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int ACCOUNT_NAME = 2; 513292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov int NORMALIZED_NAME = 3; 513392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 513492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 513592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private long lookupContactIdByDisplayNames(SQLiteDatabase db, 513692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov ArrayList<LookupKeySegment> segments) { 51375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 51385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(NameLookupColumns.NORMALIZED_NAME + " IN ("); 51395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 51405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 514192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 514292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) { 51435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov DatabaseUtils.appendEscapedSQLString(sb, segment.key); 51445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(","); 51455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.setLength(sb.length() - 1); // Last comma 51485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.append(") AND " + NameLookupColumns.NAME_TYPE + "=" + NameLookupType.NAME_COLLATION_KEY 51495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov + " AND " + RawContacts.CONTACT_ID + " NOT NULL"); 51505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 51515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Cursor c = db.query(LookupByDisplayNameQuery.TABLE, LookupByDisplayNameQuery.COLUMNS, 51525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov sb.toString(), null, null, null, null); 51535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov try { 51545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov while (c.moveToNext()) { 51555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountType = c.getString(LookupByDisplayNameQuery.ACCOUNT_TYPE); 51565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String accountName = c.getString(LookupByDisplayNameQuery.ACCOUNT_NAME); 51575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int accountHashCode = 51585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov ContactLookupKey.getAccountHashCode(accountType, accountName); 51595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov String name = c.getString(LookupByDisplayNameQuery.NORMALIZED_NAME); 51605870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 51615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 516292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if ((segment.lookupType == ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME 516392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov || segment.lookupType == ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID) 516492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov && accountHashCode == segment.accountHashCode 51655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov && segment.key.equals(name)) { 51665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov segment.contactId = c.getLong(LookupByDisplayNameQuery.CONTACT_ID); 51675870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov break; 51685870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51695870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51705870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51715870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } finally { 51725870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov c.close(); 51735870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 51755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return getMostReferencedContactId(segments); 51765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 51775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 517892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov private boolean lookupKeyContainsType(ArrayList<LookupKeySegment> segments, int lookupType) { 517992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov for (int i = 0; i < segments.size(); i++) { 518092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov LookupKeySegment segment = segments.get(i); 518192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov if (segment.lookupType == lookupType) { 518292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return true; 518392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 518492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 518592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 518692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov return false; 518792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov } 518892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov 5189ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov public void updateLookupKeyForRawContact(SQLiteDatabase db, long rawContactId) { 5190ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov mContactAggregator.updateLookupKeyForRawContact(db, rawContactId); 5191ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov } 5192ae7733451f6ddf3246efcd7fd4fc6882eefa6657Dmitri Plotnikov 51935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov /** 51945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Returns the contact ID that is mentioned the highest number of times. 51955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */ 51965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov private long getMostReferencedContactId(ArrayList<LookupKeySegment> segments) { 51975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov Collections.sort(segments); 51985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 51995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long bestContactId = -1; 52005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int bestRefCount = 0; 52015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 52025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov long contactId = -1; 52035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int count = 0; 52045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 52055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov int segmentCount = segments.size(); 52065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov for (int i = 0; i < segmentCount; i++) { 52075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov LookupKeySegment segment = segments.get(i); 52085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId != -1) { 52095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (segment.contactId == contactId) { 52105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count++; 52115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 52125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 52135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestContactId = contactId; 52145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov bestRefCount = count; 52155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov contactId = segment.contactId; 52175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov count = 1; 52185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov if (count > bestRefCount) { 52225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return contactId; 52235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } else { 52245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov return bestContactId; 52255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov } 52275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov 5228763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForContacts(SQLiteQueryBuilder qb, Uri uri, 5229763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar String[] projection) { 523082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5231916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov appendContactsTables(sb, uri, projection); 5232916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 5233916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 5234916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5235916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5236916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov /** 5237916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * Finds name lookup records matching the supplied filter, picks one arbitrary match per 5238916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov * contact and joins that with other contacts tables. 5239916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov */ 5240916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void setTablesAndProjectionMapForContactsWithSnippet(SQLiteQueryBuilder qb, Uri uri, 5241916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov String[] projection, String filter) { 5242916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5243916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov StringBuilder sb = new StringBuilder(); 5244916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov appendContactsTables(sb, uri, projection); 5245916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5246916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(" JOIN (SELECT " + 5247916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov RawContacts.CONTACT_ID + " AS snippet_contact_id"); 5248916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5249916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA_ID)) { 5250916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(", " + DataColumns.CONCRETE_ID + " AS " 5251916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov + SearchSnippetColumns.SNIPPET_DATA_ID); 5252916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5253916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 52549c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA1)) { 52559c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA1 + " AS " + SearchSnippetColumns.SNIPPET_DATA1); 5256916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5257916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 52589c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA2)) { 52599c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA2 + " AS " + SearchSnippetColumns.SNIPPET_DATA2); 5260916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5261916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 52629c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA3)) { 52639c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA3 + " AS " + SearchSnippetColumns.SNIPPET_DATA3); 52649c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov } 52659c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov 52669c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_DATA4)) { 52679c6ef008d92017108e3d10dcd8e2146eded9e148Dmitri Plotnikov sb.append(", " + Data.DATA4 + " AS " + SearchSnippetColumns.SNIPPET_DATA4); 5268916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5269916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5270916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov if (mDbHelper.isInProjection(projection, SearchSnippetColumns.SNIPPET_MIMETYPE)) { 5271916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append(", (" + 5272916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov "SELECT " + MimetypesColumns.MIMETYPE + 5273916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " FROM " + Tables.MIMETYPES + 5274916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " WHERE " + MimetypesColumns._ID + "=" + DataColumns.MIMETYPE_ID + 5275916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov ") AS " + SearchSnippetColumns.SNIPPET_MIMETYPE); 5276916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5277916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5278c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append(" FROM " + Tables.DATA_JOIN_RAW_CONTACTS + " WHERE "); 5279c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov 5280c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov if (!TextUtils.isEmpty(filter)) { 5281c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append(DataColumns.CONCRETE_ID + " IN ("); 5282c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov 5283c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov // Construct a query that gives us exactly one data _id per matching contact. 5284c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov // MIN stands in for ANY in this context. 5285c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append( 5286c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov "SELECT MIN(" + Tables.NAME_LOOKUP + "." + NameLookupColumns.DATA_ID + ")" + 5287c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 5288c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov " JOIN " + Tables.RAW_CONTACTS + 5289c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov " ON (" + RawContactsColumns.CONCRETE_ID 5290c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov + "=" + Tables.NAME_LOOKUP + "." + NameLookupColumns.RAW_CONTACT_ID + ")" + 5291c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + " GLOB '"); 5292c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append(NameNormalizer.normalize(filter)); 5293c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 5294c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + ")" + 5295c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov " GROUP BY " + RawContactsColumns.CONCRETE_CONTACT_ID + 5296c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov ")"); 5297c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov } else { 5298c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append("0"); // Empty filter - return an empty set 5299c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov } 5300c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov 5301c9e6d75562621a3dee26a99c2b082e2fd9b0c8b3Dmitri Plotnikov sb.append(") ON (" + Contacts._ID + "=snippet_contact_id)"); 5302916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5303916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setTables(sb.toString()); 5304916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionWithSnippetMap); 5305916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov } 5306916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov 5307916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov private void appendContactsTables(StringBuilder sb, Uri uri, String[] projection) { 5308763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 5309f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 5310763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 5311763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 5312d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 5313763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 5314763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getContactView(excludeRestrictedData)); 5315b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 531682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_PRESENCE)) { 531782bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 531882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + Contacts._ID + " = " + AggregatedPresenceColumns.CONTACT_ID + ")"); 531982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 5320b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 532182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS, 532282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_RES_PACKAGE, 532382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_ICON, 532482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_LABEL, 532582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Contacts.CONTACT_STATUS_TIMESTAMP)) { 53263296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 53273296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 5328a23cd5b6f478f6c9dda54173e84bd0098b9f3364Dmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 53293296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 533082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 533182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 5332ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 5333763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar private void setTablesAndProjectionMapForRawContacts(SQLiteQueryBuilder qb, Uri uri) { 5334763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar StringBuilder sb = new StringBuilder(); 5335763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = false; 5336f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 5337763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 5338763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 5339d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton excludeRestrictedData = !mDbHelper.hasAccessToRestrictedData(requestingPackage); 5340763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 5341763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getRawContactView(excludeRestrictedData)); 5342763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setTables(sb.toString()); 5343763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar qb.setProjectionMap(sRawContactsProjectionMap); 5344763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar appendAccountFromParameter(qb, uri); 5345763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 5346763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 534746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana private void setTablesAndProjectionMapForRawContactsEntities(SQLiteQueryBuilder qb, Uri uri) { 534846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana // Note: currently, "export only" equals to "restricted", but may not in the future. 534946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana boolean excludeRestrictedData = readBooleanQueryParameter(uri, 535046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana Data.FOR_EXPORT_ONLY, false); 535146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 5352f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 535346b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 535446b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana if (requestingPackage != null) { 535546b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana excludeRestrictedData = excludeRestrictedData 535646b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 535746b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 535846b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setTables(mDbHelper.getContactEntitiesView(excludeRestrictedData)); 535946b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana qb.setProjectionMap(sRawContactsEntityProjectionMap); 536046b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana appendAccountFromParameter(qb, uri); 536146b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana } 536246b7bfa3728bf878d1a9dac9fea35fa629975e1bFred Quintana 536382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 536482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov String[] projection, boolean distinct) { 536582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5366d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa // Note: currently, "export only" equals to "restricted", but may not in the future. 5367763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar boolean excludeRestrictedData = readBooleanQueryParameter(uri, 5368d237c80845d8e13164d34278d3c20e31f8d80b4dDaisuke Miyakawa Data.FOR_EXPORT_ONLY, false); 5369763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 5370f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String requestingPackage = getQueryParameter(uri, 5371763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar ContactsContract.REQUESTING_PACKAGE_PARAM_KEY); 5372763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar if (requestingPackage != null) { 5373763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar excludeRestrictedData = excludeRestrictedData 5374d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton || !mDbHelper.hasAccessToRestrictedData(requestingPackage); 5375763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar } 5376763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar 5377763100dcfabb368e72f25d24fe181c352bdb66d6Evan Millar sb.append(mDbHelper.getDataView(excludeRestrictedData)); 537882bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" data"); 537982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 53803296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated presence when requested 5381b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, Data.CONTACT_PRESENCE)) { 538282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.AGGREGATED_PRESENCE + 53833296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + AggregatedPresenceColumns.CONCRETE_CONTACT_ID + "=" 538482bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov + RawContacts.CONTACT_ID + ")"); 538582bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov } 538682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov 53873296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include aggregated status updates when requested 5388b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 538982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS, 539082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_RES_PACKAGE, 539182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_ICON, 539282bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_LABEL, 539382bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov Data.CONTACT_STATUS_TIMESTAMP)) { 53943296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + " " 53953296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.ALIAS + 539682bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov " ON (" + ContactsColumns.LAST_STATUS_UPDATE_ID + "=" 53973296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + ContactsStatusUpdatesColumns.CONCRETE_DATA_ID + ")"); 5398ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 53993296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 54003296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual presence when requested 54013296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, Data.PRESENCE)) { 54023296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 54033296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdates.DATA_ID + "=" 54043296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 54053296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 54063296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 54073296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey // Include individual status updates when requested 54083296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey if (mDbHelper.isInProjection(projection, 54093296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS, 54103296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_RES_PACKAGE, 54113296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_ICON, 54123296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_LABEL, 54133296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey Data.STATUS_TIMESTAMP)) { 54143296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 54153296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey " ON (" + StatusUpdatesColumns.CONCRETE_DATA_ID + "=" 54163296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey + DataColumns.CONCRETE_ID + ")"); 54173296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey } 54183296d3469bce0041a6cefc44d0486a2a7d0c9f82Jeff Sharkey 541982bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setTables(sb.toString()); 542082bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov qb.setProjectionMap(distinct ? sDistinctDataProjectionMap : sDataProjectionMap); 542182bd858c9911dfbd8dca52dc276333768b0a429eDmitri Plotnikov appendAccountFromParameter(qb, uri); 5422ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov } 5423ff2de103f7e3eeeff4665ef63f07460fef053d6dDmitri Plotnikov 54240a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov private void setTableAndProjectionMapForStatusUpdates(SQLiteQueryBuilder qb, 54250a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov String[] projection) { 54260a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StringBuilder sb = new StringBuilder(); 5427b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov sb.append(mDbHelper.getDataView()); 54280a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" data"); 54290a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 5430b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, StatusUpdates.PRESENCE)) { 54310a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.PRESENCE + 54320a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.PRESENCE + "." + StatusUpdates.DATA_ID 54330a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 54340a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 54350a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 5436b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov if (mDbHelper.isInProjection(projection, 54370a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS, 54380a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_RES_PACKAGE, 54390a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_ICON, 54400a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_LABEL, 54410a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov StatusUpdates.STATUS_TIMESTAMP)) { 54420a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov sb.append(" LEFT OUTER JOIN " + Tables.STATUS_UPDATES + 54430a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov " ON(" + Tables.STATUS_UPDATES + "." + StatusUpdatesColumns.DATA_ID 54440a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov + "=" + DataColumns.CONCRETE_ID + ")"); 54450a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 54460a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setTables(sb.toString()); 54470a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov qb.setProjectionMap(sStatusUpdatesProjectionMap); 54480a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov } 54490a185cdcb65d1beb2a295fffbe2ae11a6a2c097fDmitri Plotnikov 54504a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private void appendAccountFromParameter(SQLiteQueryBuilder qb, Uri uri) { 5451f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 5452f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 5453e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5454e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 5455e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 5456e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 5457fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 5458fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 5459e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 5460e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5461e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 5462e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 5463e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 5464e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 54654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 54664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountName) + " AND " 54674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 54684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov + DatabaseUtils.sqlEscapeString(accountType)); 54694a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } else { 54704a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov qb.appendWhere("1"); 54714a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 54724a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov } 54734a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov 5474e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong private String appendAccountToSelection(Uri uri, String selection) { 5475f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountName = getQueryParameter(uri, RawContacts.ACCOUNT_NAME); 5476f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov final String accountType = getQueryParameter(uri, RawContacts.ACCOUNT_TYPE); 5477e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5478e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType); 5479e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (partialUri) { 5480e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Throw when either account is incomplete 5481fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new IllegalArgumentException(mDbHelper.exceptionMessage( 5482fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE", uri)); 5483e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey } 5484e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey 5485e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // Accounts are valid by only checking one parameter, since we've 5486e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey // already ruled out partial accounts. 5487e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey final boolean validAccount = !TextUtils.isEmpty(accountName); 5488e246689441b2ff39cb97de277d6caeec95358863Jeff Sharkey if (validAccount) { 5489e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "=" 5490e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountName) + " AND " 5491e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + RawContacts.ACCOUNT_TYPE + "=" 5492e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong + DatabaseUtils.sqlEscapeString(accountType)); 5493e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong if (!TextUtils.isEmpty(selection)) { 5494e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(" AND ("); 5495e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(selection); 5496e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong selectionSb.append(')'); 5497e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 5498e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selectionSb.toString(); 5499e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } else { 5500e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong return selection; 5501e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 5502e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong } 5503e2579e029472f76b2dfda141444d775c67da0ec8Cynthia Wong 55047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 5505c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 5506c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 5507c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 5508c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 5509c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 5510f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private String getLimit(Uri uri) { 5511f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String limitParam = getQueryParameter(uri, "limit"); 5512c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 5513c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 5514c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5515c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 5516c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 5517c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 5518c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 5519c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 5520c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 5521c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5522c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 5523c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 5524c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 5525c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 5526c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5527c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5528c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 55295e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov /** 55305e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * Returns true if all the characters are meaningful as digits 55315e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov * in a phone number -- letters, digits, and a few punctuation marks. 55325e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov */ 55335e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private boolean isPhoneNumber(CharSequence cons) { 55345e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov int len = cons.length(); 55355e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 55365e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov for (int i = 0; i < len; i++) { 55375e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov char c = cons.charAt(i); 55385e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 55395e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= '0') && (c <= '9')) { 55405e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 55415e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55425e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c == ' ') || (c == '-') || (c == '(') || (c == ')') || (c == '.') || (c == '+') 55435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov || (c == '#') || (c == '*')) { 55445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 55455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55465e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'A') && (c <= 'Z')) { 55475e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 55485e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55495e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov if ((c >= 'a') && (c <= 'z')) { 55505e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov continue; 55515e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 55535e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return false; 55545e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55555e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 55565e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov return true; 55575e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 55585e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 555900ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 5560d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 556170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 556270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 5563fada1f08e7ffc8012bf2175f61f3ef3270eba9ecDmitri Plotnikov return RawContactsColumns.CONCRETE_IS_RESTRICTED + "=0"; 556470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 556570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 556670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 556770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 5568d91272b48f97243533c6580981e12a4847b5783fJeff Hamilton if (mDbHelper.hasAccessToRestrictedData()) { 556970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 557067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 55715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 55725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 5573619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 5574619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 5575619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 5576b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov @Override 5577b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 5578b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov int match = sUriMatcher.match(uri); 5579b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov switch (match) { 5580d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey case CONTACTS_PHOTO: { 5581e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov return openPhotoAssetFile(uri, mode, 5582e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov Data._ID + "=" + Contacts.PHOTO_ID + " AND " + RawContacts.CONTACT_ID + "=?", 5583e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov new String[]{uri.getPathSegments().get(1)}); 5584e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 5585b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5586e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov case DATA_ID: { 5587e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov return openPhotoAssetFile(uri, mode, 5588e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov Data._ID + "=? AND " + Data.MIMETYPE + "='" + Photo.CONTENT_ITEM_TYPE + "'", 55894da1b8ded4435a3392bac3511c67182015e0953fDmitri Plotnikov new String[]{uri.getPathSegments().get(1)}); 5590d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5591d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5592f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: { 559342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKey = Uri.encode(uri.getPathSegments().get(2)); 559442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann mSelectionArgs1[0] = String.valueOf(lookupContactIdByLookupKey(mDb, lookupKey)); 559542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + "=?"; 559642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 559742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // When opening a contact as file, we pass back contents as a 559842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // vCard-encoded stream. We build into a local buffer first, 559942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann // then pipe into MemoryFile once the exact size is known. 560042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 560142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann outputRawContactsAsVCard(localStream, selection, mSelectionArgs1); 560242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann return buildAssetFileDescriptor(localStream); 560342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 560442aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann 560542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: { 560642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String lookupKeys = uri.getPathSegments().get(2); 560742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String[] loopupKeyList = lookupKeys.split(":"); 560842aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final StringBuilder inBuilder = new StringBuilder(); 560942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann int index = 0; 5610d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // SQLite has limits on how many parameters can be used 5611d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann // so the IDs are concatenated to a query string here instead 561242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann for (String lookupKey : loopupKeyList) { 561342aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann if (index == 0) { 5614d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append("("); 561542aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } else { 5616d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append(","); 561742aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 5618d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann inBuilder.append(lookupContactIdByLookupKey(mDb, lookupKey)); 561942aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann index++; 562042aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann } 562142aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann inBuilder.append(')'); 562242aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann final String selection = Contacts._ID + " IN " + inBuilder.toString(); 5623d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5624d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // When opening a contact as file, we pass back contents as a 5625d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // vCard-encoded stream. We build into a local buffer first, 5626d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey // then pipe into MemoryFile once the exact size is known. 5627d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final ByteArrayOutputStream localStream = new ByteArrayOutputStream(); 5628d5a176cfe6d8701ae8b7882596711e5fc2746be1Daniel Lehmann outputRawContactsAsVCard(localStream, selection, null); 5629d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return buildAssetFileDescriptor(localStream); 5630d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5631b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5632b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov default: 5633fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov throw new FileNotFoundException(mDbHelper.exceptionMessage("File does not exist", 5634fa4a38c9d54f3e3aad4674867bb1250f450c0b95Dmitri Plotnikov uri)); 5635b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 5636b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov } 5637b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5638e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov private AssetFileDescriptor openPhotoAssetFile(Uri uri, String mode, String selection, 5639e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String[] selectionArgs) 5640e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throws FileNotFoundException { 5641e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov if (!"r".equals(mode)) { 5642e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov throw new FileNotFoundException(mDbHelper.exceptionMessage("Mode " + mode 5643e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov + " not supported.", uri)); 5644e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 5645e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 5646e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov String sql = 5647e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov "SELECT " + Photo.PHOTO + " FROM " + mDbHelper.getDataView() + 5648e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov " WHERE " + selection; 5649e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov SQLiteDatabase db = mDbHelper.getReadableDatabase(); 5650e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov return SQLiteContentHelper.getBlobColumnAsAssetFile(db, sql, 5651e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov selectionArgs); 5652e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov } 5653e8d2c8276d6331843410c97751e46fc50b257379Dmitri Plotnikov 5654d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private static final String CONTACT_MEMORY_FILE_NAME = "contactAssetFile"; 5655d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5656d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 5657d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Build a {@link AssetFileDescriptor} through a {@link MemoryFile} with the 5658d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * contents of the given {@link ByteArrayOutputStream}. 5659d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 5660d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private AssetFileDescriptor buildAssetFileDescriptor(ByteArrayOutputStream stream) { 5661d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey AssetFileDescriptor fd = null; 5662d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey try { 5663d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey stream.flush(); 5664d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5665d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final byte[] byteData = stream.toByteArray(); 5666d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final int size = byteData.length; 5667d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5668d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final MemoryFile memoryFile = new MemoryFile(CONTACT_MEMORY_FILE_NAME, size); 5669d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.writeBytes(byteData, 0, 0, size); 5670d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey memoryFile.deactivate(); 5671b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 5672d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey fd = AssetFileDescriptor.fromMemoryFile(memoryFile); 5673d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } catch (IOException e) { 5674d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Problem writing stream into an AssetFileDescriptor: " + e.toString()); 5675d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5676d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return fd; 5677d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5678d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5679d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey /** 5680d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * Output {@link RawContacts} matching the requested selection in the vCard 5681d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * format to the given {@link OutputStream}. This method returns silently if 5682d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey * any errors encountered. 5683d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey */ 5684d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey private void outputRawContactsAsVCard(OutputStream stream, String selection, 5685d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey String[] selectionArgs) { 5686d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey final Context context = this.getContext(); 56877a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa final VCardComposer composer = 56887a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa new VCardComposer(context, VCardConfig.VCARD_TYPE_DEFAULT, false); 5689d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.addHandler(composer.new HandlerForOutputStream(stream)); 5690d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5691f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey // No extra checks since composer always uses restricted views 56927a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa if (!composer.init(selection, selectionArgs)) { 56937a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa Log.w(TAG, "Failed to init VCardComposer"); 5694d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey return; 56957a2a564e9a72969999821142c821eb1b912f0d95Daisuke Miyakawa } 5696d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey 5697d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey while (!composer.isAfterLast()) { 5698d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey if (!composer.createOneEntry()) { 5699d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey Log.w(TAG, "Failed to output a contact."); 5700d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5701d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5702d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey composer.terminate(); 5703d173ca0f279d89030cc7e3f1aadd18755a2e8766Jeff Sharkey } 5704b3f909fee75cb384fc381ec5ce70dd001669f945Dmitri Plotnikov 57054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 57064f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 5707a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 57084f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 5709b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS: 5710be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return Contacts.CONTENT_TYPE; 57112d2ec88b7af615b2f05e987da45425be9cace1baTom O'Neill case CONTACTS_LOOKUP: 5712b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_ID: 5713b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case CONTACTS_LOOKUP_ID: 5714b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_ITEM_TYPE; 5715f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey case CONTACTS_AS_VCARD: 571642aff67de3f0f4b8664a74fe6ff63ae191aa51bfDaniel Lehmann case CONTACTS_AS_MULTI_VCARD: 5717f9aeb84d61c01a473819e9173f8311ca5d678a8dJeff Sharkey return Contacts.CONTENT_VCARD_TYPE; 5718b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS: 5719be84be1519fe0b73f47c2b2fe9badb8a3e833b28Dmitri Plotnikov return RawContacts.CONTENT_TYPE; 5720b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case RAW_CONTACTS_ID: 5721b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return RawContacts.CONTENT_ITEM_TYPE; 5722508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 5723b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return mDbHelper.getDataMimeType(ContentUris.parseId(uri)); 572448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES: 572548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_TYPE; 572648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case PHONES_ID: 572748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Phone.CONTENT_ITEM_TYPE; 57289005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov case PHONE_LOOKUP: 57299005e312949b4624aae6953dbdab2eaee1650835Dmitri Plotnikov return PhoneLookup.CONTENT_TYPE; 573048828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS: 573148828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_TYPE; 573248828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case EMAILS_ID: 573348828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return Email.CONTENT_ITEM_TYPE; 573448828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS: 573548828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_TYPE; 573648828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov case POSTALS_ID: 573748828f54daafda2edb122258c4c6a7d2ca704128Dmitri Plotnikov return StructuredPostal.CONTENT_ITEM_TYPE; 5738b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTIONS: 5739b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_TYPE; 5740b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_EXCEPTION_ID: 5741b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return AggregationExceptions.CONTENT_ITEM_TYPE; 5742b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case SETTINGS: 5743b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Settings.CONTENT_TYPE; 5744b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov case AGGREGATION_SUGGESTIONS: 5745b4cfef6f658ecade496351107f6ed2a4818f3e3aDmitri Plotnikov return Contacts.CONTENT_TYPE; 5746c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 5747c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 5748c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 5749c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 5750d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov 575161efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov default: 575261efab87c2c8166b3cd69ed1a908d1c0d7271d0bDmitri Plotnikov return mLegacyApiSupport.getType(uri); 57534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 57544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 57557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 57565dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void setDisplayName(long rawContactId, int displayNameSource, 57575dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov String displayNamePrimary, String displayNameAlternative, String phoneticName, 57585dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov int phoneticNameStyle, String sortKeyPrimary, String sortKeyAlternative) { 57595dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(1, displayNameSource); 57605dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 2, displayNamePrimary); 57615dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 3, displayNameAlternative); 57625dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 4, phoneticName); 57635dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(5, phoneticNameStyle); 57645dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 6, sortKeyPrimary); 57655dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mRawContactDisplayNameUpdate, 7, sortKeyAlternative); 57665dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mRawContactDisplayNameUpdate.bindLong(8, rawContactId); 576725abcf949c0dd826a770b437489b83de48975ceaDmitri Plotnikov mRawContactDisplayNameUpdate.execute(); 57683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 57693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 577073776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov /** 577173776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov * Sets the {@link RawContacts#DIRTY} for the specified raw contact. 577273776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov */ 577373776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov private void setRawContactDirty(long rawContactId) { 5774a8d8b1cb48a6e94645dbce836193b40c7481356cDmitri Plotnikov mDirtyRawContacts.add(rawContactId); 577573776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov } 577673776ffd5c00e94db987ee30864e9c7a8396d22dDmitri Plotnikov 5777c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 5778c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 5779c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 5780c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 5781c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 5782c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 5783653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { 5784c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 5785653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(2, mimeTypeId); 5786653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetPrimaryStatement.bindLong(3, rawContactId); 5787c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 5788c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 5789c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 5790c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 5791c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 5792c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 5793c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 5794c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 5795c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 5796653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov private void setIsSuperPrimary(long rawContactId, long dataId, long mimeTypeId) { 5797c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 5798653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(2, mimeTypeId); 5799653f73c9417ee0d2cf90e9aacd32848016747cf7Dmitri Plotnikov mSetSuperPrimaryStatement.bindLong(3, rawContactId); 5800c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 5801c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 5802ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 5803813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov public String insertNameLookupForEmail(long rawContactId, long dataId, String email) { 5804f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(email)) { 5805813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return null; 5806f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5807f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5808b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov String address = mDbHelper.extractHandleFromEmailAddress(email); 5809b06484032125877d1a89785a1a912ca58c12d448Dmitri Plotnikov if (address == null) { 5810813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return null; 5811f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5812f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5813f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 5814f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.EMAIL_BASED_NICKNAME, NameNormalizer.normalize(address)); 5815813fd5712e0ad264ff6907c85d68a01fb1255d28Dmitri Plotnikov return address; 5816f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5817f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5818f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5819f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Normalizes the nickname and inserts it in the name lookup table. 5820f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5821f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookupForNickname(long rawContactId, long dataId, String nickname) { 5822f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov if (TextUtils.isEmpty(nickname)) { 5823f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov return; 5824f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5825f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5826f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov insertNameLookup(rawContactId, dataId, 5827f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov NameLookupType.NICKNAME, NameNormalizer.normalize(nickname)); 5828f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5829f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5830a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka public void insertNameLookupForOrganization(long rawContactId, long dataId, String company, 5831a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka String title) { 5832a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(company)) { 5833a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 5834a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(company)); 5835a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 5836a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka if (!TextUtils.isEmpty(title)) { 5837a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka insertNameLookup(rawContactId, dataId, 5838a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka NameLookupType.ORGANIZATION, NameNormalizer.normalize(title)); 5839a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 5840a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka } 5841f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5842d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov public void insertNameLookupForStructuredName(long rawContactId, long dataId, String name, 5843d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov int fullNameStyle) { 5844d806946b6561dca3f34ded156c6ee89a5113996eDmitri Plotnikov mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name, fullNameStyle); 5845f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5846f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5847f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov private class StructuredNameLookupBuilder extends NameLookupBuilder { 5848f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5849f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public StructuredNameLookupBuilder(NameSplitter splitter) { 5850f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov super(splitter); 5851f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5852f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5853f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 5854f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected void insertNameLookup(long rawContactId, long dataId, int lookupType, 5855f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov String name) { 5856f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov ContactsProvider2.this.insertNameLookup(rawContactId, dataId, lookupType, name); 5857f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5858f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5859f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov @Override 5860f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov protected String[] getCommonNicknameClusters(String normalizedName) { 5861d0569511c4b9eb961d5a73be16edb9767fa9c2ebDmitri Plotnikov return mCommonNicknameCache.getCommonNicknameClusters(normalizedName); 5862f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5863f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5864f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 586548786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov public void insertNameLookupForPhoneticName(long rawContactId, long dataId, 586648786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov ContentValues values) { 586748786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (values.containsKey(StructuredName.PHONETIC_FAMILY_NAME) 586848786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov || values.containsKey(StructuredName.PHONETIC_GIVEN_NAME) 586948786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov || values.containsKey(StructuredName.PHONETIC_MIDDLE_NAME)) { 587048786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov insertNameLookupForPhoneticName(rawContactId, dataId, 587148786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov values.getAsString(StructuredName.PHONETIC_FAMILY_NAME), 587248786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov values.getAsString(StructuredName.PHONETIC_MIDDLE_NAME), 587348786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov values.getAsString(StructuredName.PHONETIC_GIVEN_NAME)); 587448786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 587548786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 587648786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov 587748786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov public void insertNameLookupForPhoneticName(long rawContactId, long dataId, String familyName, 587848786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov String middleName, String givenName) { 587948786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov mSb.setLength(0); 588048786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (familyName != null) { 588148786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov mSb.append(familyName.trim()); 588248786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 588348786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (middleName != null) { 588448786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov mSb.append(middleName.trim()); 588548786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 588648786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (givenName != null) { 588748786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov mSb.append(givenName.trim()); 588848786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 588948786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov 589048786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov if (mSb.length() > 0) { 589148786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov insertNameLookup(rawContactId, dataId, NameLookupType.NAME_COLLATION_KEY, 589248786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov NameNormalizer.normalize(mSb.toString())); 589348786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 58943b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov 58953b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov if (givenName != null) { 58963b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov // We want the phonetic given name to be used for search, but not for aggregation, 58973b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov // which is why we are using NAME_SHORTHAND rather than NAME_COLLATION_KEY 58983b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov insertNameLookup(rawContactId, dataId, NameLookupType.NAME_SHORTHAND, 58993b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov NameNormalizer.normalize(givenName.trim())); 59003b10d3a1ed1052dcdf529da370cb71b74164b158Dmitri Plotnikov } 590148786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov } 590248786768751cdd9868fb3cf3c82d63f277a54b6fDmitri Plotnikov 5903f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5904f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Inserts a record in the {@link Tables#NAME_LOOKUP} table. 5905f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5906f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void insertNameLookup(long rawContactId, long dataId, int lookupType, String name) { 59075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(1, rawContactId); 59085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(2, dataId); 59095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupInsert.bindLong(3, lookupType); 59105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov bindString(mNameLookupInsert, 4, name); 5911f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupInsert.executeInsert(); 5912f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5913f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 5914f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov /** 5915f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov * Deletes all {@link Tables#NAME_LOOKUP} table rows associated with the specified data element. 5916f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov */ 5917f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov public void deleteNameLookup(long dataId) { 59185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov mNameLookupDelete.bindLong(1, dataId); 5919f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov mNameLookupDelete.execute(); 5920f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov } 5921f23764675b35b5262a39c79aad8e9842460274b2Dmitri Plotnikov 59222d89933b87a15ae5ed5d6b6ec4220ac085695adaDmitri Plotnikov public void appendContactFilterAsNestedQuery(StringBuilder sb, String filterParam) { 5923d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 5924d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov "SELECT DISTINCT " + RawContacts.CONTACT_ID + 5925d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.RAW_CONTACTS + 5926d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " JOIN " + Tables.NAME_LOOKUP + 5927d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " ON(" + RawContactsColumns.CONCRETE_ID + "=" 5928d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov + NameLookupColumns.RAW_CONTACT_ID + ")" + 5929d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE normalized_name GLOB '"); 5930e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 5931916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov sb.append("*' AND " + NameLookupColumns.NAME_TYPE + 5932916f2d7104bfba857412a66b40ed60fea6546222Dmitri Plotnikov " IN(" + CONTACT_LOOKUP_NAME_TYPES + "))"); 5933e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov } 5934e46667e641cd1c60998e1ccab4b60531d5b12ef7Dmitri Plotnikov 59355ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 5936c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 59377318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam); 5938c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 5939c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 5940c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 59417318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam) { 59427318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov appendRawContactsByNormalizedNameFilter(sb, NameNormalizer.normalize(filterParam), true); 59435e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov } 59445e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov 59455e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov private void appendRawContactsByNormalizedNameFilter(StringBuilder sb, String normalizedName, 59467318f9e11bdac5ea1ff5e6a8143b90c4e5c497f6Dmitri Plotnikov boolean allowEmailMatch) { 5947d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov sb.append("(" + 5948dc947a9d03279eab0fb7c3b9d8ffbb492c1e2062Dmitri Plotnikov "SELECT " + NameLookupColumns.RAW_CONTACT_ID + 5949d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " FROM " + Tables.NAME_LOOKUP + 5950d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " WHERE " + NameLookupColumns.NORMALIZED_NAME + 5951d60cf9ba1d039f1a22375f56c18356e0d4f8ca14Dmitri Plotnikov " GLOB '"); 59525e99505757457d11d9388f6d04960e97fc776a59Dmitri Plotnikov sb.append(normalizedName); 5953a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka sb.append("*' AND " + NameLookupColumns.NAME_TYPE + " IN (" 5954a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NAME_COLLATION_KEY + "," 5955a5d05d90333a70d471d78e82caeb5cfa2e4d4c59Tadashi G. Takaoka + NameLookupType.NICKNAME + "," 59564cd13c4266d8e476e1a49c4b6bcd5b18c33d0de3Bai Tao + NameLookupType.NAME_SHORTHAND + "," 5957f84478382761d74b9fb98c4189de66002c04cef8Sang-il, Lee + NameLookupType.ORGANIZATION + "," 595889f1f71495aedc58252b3f58a46a036986c319d2Dmitri Plotnikov + NameLookupType.NAME_CONSONANTS); 595920938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov if (allowEmailMatch) { 596020938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov sb.append("," + NameLookupType.EMAIL_BASED_NICKNAME); 596120938cd6df602bf08c232b32fc047592c1561347Dmitri Plotnikov } 596289f1f71495aedc58252b3f58a46a036986c319d2Dmitri Plotnikov sb.append("))"); 5963ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 5964ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 59654a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov /** 59664a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov * Inserts an argument at the beginning of the selection arg list. 59674a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov */ 59684a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov private String[] insertSelectionArg(String[] selectionArgs, String arg) { 5969b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 5970b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 5971b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 5972b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 5973b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 59744a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov newSelectionArgs[0] = arg; 59754a023070dab9a069be4cac5f5ba5554b66238484Dmitri Plotnikov System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length); 5976b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 5977b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5978b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 5979caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov 59805e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar private String[] appendProjectionArg(String[] projection, String arg) { 59815e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar if (projection == null) { 59825e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return null; 59835e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 59845e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar final int length = projection.length; 59855e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar String[] newProjection = new String[length + 1]; 59865e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar System.arraycopy(projection, 0, newProjection, 0, length); 59875e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar newProjection[length] = arg; 59885e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar return newProjection; 59895e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar } 59905e28b3a5e44bf4f2c0980c50a2ab35350fc5f230Evan Millar 5991caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov protected Account getDefaultAccount() { 5992caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov AccountManager accountManager = AccountManager.get(getContext()); 5993caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov try { 5994df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana Account[] accounts = accountManager.getAccountsByTypeAndFeatures(DEFAULT_ACCOUNT_TYPE, 5995df9fd6b239de5829b04cb413e4dfa3e6da649c38Fred Quintana new String[] {FEATURE_LEGACY_HOSTED_OR_GOOGLE}, null, null).getResult(); 5996caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov if (accounts != null && accounts.length > 0) { 5997caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov return accounts[0]; 5998caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 5999caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } catch (Throwable e) { 60006f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov Log.e(TAG, "Cannot determine the default account for contacts compatibility", e); 6001caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 60026f7446a25ecb55ee213eaa7702837cdf32e68777Dmitri Plotnikov return null; 6003caa1cf4ef062f163ac5e370cebc0e47b5ae7460eDmitri Plotnikov } 6004f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 600573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov /** 600673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov * Returns true if the specified account type is writable. 600773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov */ 600873f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov protected boolean isWritableAccount(String accountType) { 6009bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov if (accountType == null) { 6010bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov return true; 6011bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov } 6012bc487a312a84972f03776cdc5784cc132a57f8fdDmitri Plotnikov 601373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov Boolean writable = mAccountWritability.get(accountType); 601473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable != null) { 601573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 601673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 601773f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 6018627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov IContentService contentService = ContentResolver.getContentService(); 6019627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov try { 6020627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { 6021627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov if (ContactsContract.AUTHORITY.equals(sync.authority) && 602273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov accountType.equals(sync.accountType)) { 602373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = sync.supportsUploading(); 602473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov break; 6025627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 6026627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 6027627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } catch (RemoteException e) { 6028627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov Log.e(TAG, "Could not acquire sync adapter types"); 6029627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 603073f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 603173f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov if (writable == null) { 603273f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov writable = false; 603373f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov } 603473f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov 603573f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov mAccountWritability.put(accountType, writable); 603673f1f396c155b247b903d8f4111db17d3e13dc4dDmitri Plotnikov return writable; 6037627152453c692915ac79191acd1d2d2a4dd6fb0dDmitri Plotnikov } 6038b4e61e064b59e8076df81b061add9fb358fd2ed9Dmitri Plotnikov 6039f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static boolean readBooleanQueryParameter(Uri uri, String parameter, 6040f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean defaultValue) { 6041f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6042f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov // Manually parse the query, which is much faster than calling uri.getQueryParameter 6043f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 6044f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 6045f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 6046f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6047f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6048f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = query.indexOf(parameter); 6049f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 6050f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return defaultValue; 6051f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6052f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6053f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameter.length(); 6054f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6055f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return !matchQueryParameter(query, index, "=0", false) 6056f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && !matchQueryParameter(query, index, "=false", true); 6057f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6058f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6059f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov private static boolean matchQueryParameter(String query, int index, String value, 6060f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov boolean ignoreCase) { 6061f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int length = value.length(); 6062f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return query.regionMatches(ignoreCase, index, value, 0, length) 6063f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov && (query.length() == index + length || query.charAt(index + length) == '&'); 6064f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6065f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6066f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /** 6067f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov * A fast re-implementation of {@link Uri#getQueryParameter} 6068f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov */ 6069f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov /* package */ static String getQueryParameter(Uri uri, String parameter) { 6070f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String query = uri.getEncodedQuery(); 6071f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query == null) { 6072f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 6073f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6074f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6075f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int queryLength = query.length(); 6076f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int parameterLength = parameter.length(); 6077f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6078f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov String value; 6079f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int index = 0; 6080f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov while (true) { 6081f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index = query.indexOf(parameter, index); 6082f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (index == -1) { 6083f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 6084f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6085f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6086f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index += parameterLength; 6087f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6088f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (queryLength == index) { 6089f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return null; 6090f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6091f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6092f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (query.charAt(index) == '=') { 6093f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov index++; 6094f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov break; 6095f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6096f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6097f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6098f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov int ampIndex = query.indexOf('&', index); 6099f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov if (ampIndex == -1) { 6100f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index); 6101f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } else { 6102f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov value = query.substring(index, ampIndex); 6103f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 6104f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov 6105f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov return Uri.decode(value); 6106f7f747a00f4fa7a9e564507693419a5a8db0eb8fDmitri Plotnikov } 61075dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 61085dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void bindString(SQLiteStatement stmt, int index, String value) { 61095dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (value == null) { 61105dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindNull(index); 61115dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 61125dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindString(index, value); 61135dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 61145dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 61155dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov 61165dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov private void bindLong(SQLiteStatement stmt, int index, Number value) { 61175dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov if (value == null) { 61185dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindNull(index); 61195dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } else { 61205dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov stmt.bindLong(index, value.longValue()); 61215dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 61225dd6d5d4acb93adc05f1fde904080787f2397f51Dmitri Plotnikov } 61234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 6124