ContactsProvider2.java revision 7a4550f2afb24b2112b6c937f416c6f46ece35f4
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 1967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport com.android.internal.content.SyncStateContentProviderHelper; 2028f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.AggregationExceptionColumns; 2128f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.Clauses; 22d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport com.android.providers.contacts.OpenHelper.ContactsColumns; 2328f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.DataColumns; 2428f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.GroupsColumns; 2528f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.MimetypesColumns; 2667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport com.android.providers.contacts.OpenHelper.PackagesColumns; 27d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport com.android.providers.contacts.OpenHelper.PhoneColumns; 2828f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.PhoneLookupColumns; 29d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport com.android.providers.contacts.OpenHelper.RawContactsColumns; 3028f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.Tables; 31e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikovimport com.google.android.collect.Lists; 32e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 33b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 34c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.app.SearchManager; 354f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.content.ContentProvider; 3667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentProviderOperation; 3767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentProviderResult; 3835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 3967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.ContentValues; 4067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.Context; 4135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.Entity; 4267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.EntityIterator; 437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport android.content.OperationApplicationException; 443d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences; 4567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 463d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.content.SharedPreferences.Editor; 4767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.pm.PackageManager; 484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 49ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 50b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.database.sqlite.SQLiteCursor; 514f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 53c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 55619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.os.Binder; 56b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 573d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikovimport android.preference.PreferenceManager; 58508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 59de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract; 603cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikovimport android.provider.Contacts.People; 61b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 62de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds; 63d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.Contacts; 64de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.Data; 65ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.Groups; 661f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkeyimport android.provider.ContactsContract.Presence; 67d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.BaseTypes; 69ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email; 70ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 74de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds.Phone; 754097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 7667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 77d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.Contacts.AggregationSuggestions; 78a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 79a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 80c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 827e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 83b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 864f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 874f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 89035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintanapublic class ContactsProvider2 extends ContentProvider { 90b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey // TODO: clean up debug tag and rename this class 91b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey private static final String TAG = "ContactsProvider ~~~~"; 924f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 93619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 94619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: check for restricted flag during insert(), update(), and delete() calls 95619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 993d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /** 1003d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * Shared preference key for the legacy contact import version. The need for a version 1013d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * as opposed to a boolean flag is that if we discover bugs in the contact import process, 1023d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov * we can trigger re-import by incrementing the import version. 1033d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov */ 1043d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final String PREF_CONTACTS_IMPORTED = "contacts_imported_v1"; 1053d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private static final int PREF_CONTACTS_IMPORT_VERSION = 1; 1063d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 107a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 1084f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 109d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 110d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.TIMES_CONTACTED + " DESC, " 111d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.DISPLAY_NAME + " ASC"; 112d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 113d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 114d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 115d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 116d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 117d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 118d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_DATA = 1002; 119d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_SUMMARY = 1003; 1202815f58f72f109790585931f601a63ddc02536a5Evan Millar private static final int CONTACTS_RAW_CONTACTS = 1004; 1212815f58f72f109790585931f601a63ddc02536a5Evan Millar private static final int CONTACTS_SUMMARY_ID = 1005; 1222815f58f72f109790585931f601a63ddc02536a5Evan Millar private static final int CONTACTS_SUMMARY_FILTER = 1006; 1232815f58f72f109790585931f601a63ddc02536a5Evan Millar private static final int CONTACTS_SUMMARY_STREQUENT = 1007; 1242815f58f72f109790585931f601a63ddc02536a5Evan Millar private static final int CONTACTS_SUMMARY_STREQUENT_FILTER = 1008; 1252815f58f72f109790585931f601a63ddc02536a5Evan Millar private static final int CONTACTS_SUMMARY_GROUP = 1009; 1264f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1275ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 1285ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 1295ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 13028ab0f857caa92402878244d9c5ea2a59e070935Jeff Sharkey private static final int CONTACTS_FILTER_EMAIL = 2005; 1314f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1326bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 1336bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 134ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 135ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES_FILTER = 3003; 136ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int POSTALS = 3004; 137a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1386bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 1396bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 140b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 141b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 142b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 1431f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private static final int PRESENCE = 7000; 1441f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private static final int PRESENCE_ID = 7001; 1451f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 14631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 14731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 148ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 149ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 150ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 151ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 15235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 15335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 154c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 155c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 156c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 15767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private interface ContactsQuery { 1585ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final String TABLE = Tables.RAW_CONTACTS; 1599261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 16067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 1616cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 1626cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 1636cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 164ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 165ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 16767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int ACCOUNT_NAME = 1; 16867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int ACCOUNT_TYPE = 2; 16967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 17067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 171d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataRawContactsQuery { 1725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final String TABLE = Tables.DATA_JOIN_MIMETYPE_RAW_CONTACTS; 17367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 17467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 1756cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 1763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 177d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov RawContacts.CONTACT_ID, 1786cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.IS_RESTRICTED, 1793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.MIMETYPE, 180ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 181ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1825ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 18367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 184d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 18567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int IS_RESTRICTED = 3; 18667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int MIMETYPE = 4; 18767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 18867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 189d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 190d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final String TABLE = Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS; 19167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 19267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 1936cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 1943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 195d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.CONCRETE_ID, 1963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.CONCRETE_ID, 1973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Phone.NUMBER, 1983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Email.DATA, 199d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.OPTIMAL_PRIMARY_PHONE_ID, 200d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.FALLBACK_PRIMARY_PHONE_ID, 201d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.OPTIMAL_PRIMARY_EMAIL_ID, 202d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.FALLBACK_PRIMARY_EMAIL_ID, 203ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 204ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 205d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 20667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 207d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 20867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int MIMETYPE_ID = 3; 20967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int PHONE_NUMBER = 4; 21067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int EMAIL_DATA = 5; 21167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int OPTIMAL_PHONE_ID = 6; 21267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int FALLBACK_PHONE_ID = 7; 21367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int OPTIMAL_EMAIL_ID = 8; 21467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int FALLBACK_EMAIL_ID = 9; 21580c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 216ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2171f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private interface DisplayNameQuery { 21967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final String[] COLUMNS = new String[] { 2223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 2243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA2, 2253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov StructuredName.DISPLAY_NAME, 2263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 0; 2293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 1; 2303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA2 = 2; 2313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DISPLAY_NAME = 3; 2323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private interface DataQuery { 23567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final String[] COLUMNS = new String[] { 2383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 2393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2405ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID, 2413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 2423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA1, 2433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA2, 2443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA3, 2453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA4, 2463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA5, 2473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA6, 2483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA7, 2493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA8, 2503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA9, 2513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA10, 25267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Data.DATA11, 25367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Data.DATA12, 25467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Data.DATA13, 25567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Data.DATA14, 25667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Data.DATA15, 2573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int ID = 0; 2603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 1; 2615ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 2; 2623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 3; 2633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA1 = 4; 2643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA2 = 5; 2653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA3 = 6; 2663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA4 = 7; 2673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA5 = 8; 2683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA6 = 9; 2693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA7 = 10; 2703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA8 = 11; 2713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA9 = 12; 2723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA10 = 13; 27367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA11 = 14; 27467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA12 = 15; 27567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA13 = 16; 27667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA14 = 17; 27767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA15 = 18; 2783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 28020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private interface DataIdQuery { 281321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana String[] COLUMNS = { Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE }; 28220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 28320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int _ID = 0; 284321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int RAW_CONTACT_ID = 1; 285321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana int MIMETYPE = 2; 28620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 28720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov // Higher number represents higher priority in choosing what data to use for the display name 2893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DISPLAY_NAME_PRIORITY_EMAIL = 1; 2903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DISPLAY_NAME_PRIORITY_PHONE = 2; 2913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DISPLAY_NAME_PRIORITY_ORGANIZATION = 3; 2923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DISPLAY_NAME_PRIORITY_STRUCTURED_NAME = 4; 2933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final HashMap<String, Integer> sDisplayNamePriorities; 2953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov static { 2963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov sDisplayNamePriorities = new HashMap<String, Integer>(); 2973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov sDisplayNamePriorities.put(StructuredName.CONTENT_ITEM_TYPE, 2983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DISPLAY_NAME_PRIORITY_STRUCTURED_NAME); 2993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov sDisplayNamePriorities.put(Organization.CONTENT_ITEM_TYPE, 3003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DISPLAY_NAME_PRIORITY_ORGANIZATION); 3013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov sDisplayNamePriorities.put(Phone.CONTENT_ITEM_TYPE, 3023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DISPLAY_NAME_PRIORITY_PHONE); 3033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov sDisplayNamePriorities.put(Email.CONTENT_ITEM_TYPE, 3043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DISPLAY_NAME_PRIORITY_EMAIL); 3053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 30631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 3076bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** Contains just the contacts columns */ 3084f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 309d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Contains the contact columns along with primary phone */ 310d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sContactsSummaryProjectionMap; 311d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Contains the data, contacts, and contact columns, for joined tables. */ 3120c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar private static final HashMap<String, String> sDataRawContactsContactProjectionMap; 313d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Contains the data, contacts, group sourceid and contact columns, for joined tables. */ 3140c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar private static final HashMap<String, String> sDataRawContactsGroupsContactProjectionMap; 3152815f58f72f109790585931f601a63ddc02536a5Evan Millar /** Contains the contacts, and raw contact columns, for joined tables. */ 3162815f58f72f109790585931f601a63ddc02536a5Evan Millar private static final HashMap<String, String> sRawContactsContactsProjectionMap; 317d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Contains just the contacts columns */ 318d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 319a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** Contains just the data columns */ 3209261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana private static final HashMap<String, String> sDataGroupsProjectionMap; 3219261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 3220c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar private static final HashMap<String, String> sDataRawContactsGroupsProjectionMap; 323a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** Contains the data and contacts columns, for joined tables */ 3240c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar private static final HashMap<String, String> sDataRawContactsProjectionMap; 325ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 326ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 327ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 328ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 329373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 330b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 331373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains Presence columns */ 332373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov private static final HashMap<String, String> sPresenceProjectionMap; 3337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 334c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Sql select statement that returns the contact id associated with a data record. */ 335d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String sNestedRawContactIdSelect; 336c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Sql select statement that returns the mimetype id associated with a data record. */ 337c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private static final String sNestedMimetypeSelect; 338d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Sql select statement that returns the contact id associated with a contact record. */ 339d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String sNestedContactIdSelect; 340d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Sql select statement that returns a list of contact ids associated with an contact record. */ 341c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private static final String sNestedContactIdListSelect; 342c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Sql where statement used to match all the data records that need to be updated when a new 343c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * "primary" is selected.*/ 344c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private static final String sSetPrimaryWhere; 345c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Sql where statement used to match all the data records that need to be updated when a new 346c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * "super primary" is selected.*/ 347c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private static final String sSetSuperPrimaryWhere; 348b67163a1088f09c59f324350662eb18772fac6b6Evan Millar /** Sql where statement for filtering on groups. */ 349d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String sContactsInGroupSelect; 350c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 351c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 3523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 353c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 354d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Precompiled sql statement for incrementing times contacted for an contact */ 355f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private SQLiteStatement mLastTimeContactedUpdate; 3563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 3573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private SQLiteStatement mContactDisplayNameUpdate; 358a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 3594f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 3604f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 361a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 362d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 363d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 364d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 3652815f58f72f109790585931f601a63ddc02536a5Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/raw_contacts", CONTACTS_RAW_CONTACTS); 366d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts_summary", CONTACTS_SUMMARY); 367d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts_summary/#", CONTACTS_SUMMARY_ID); 368d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts_summary/filter/*", 369d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov CONTACTS_SUMMARY_FILTER); 370d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts_summary/strequent/", 371d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov CONTACTS_SUMMARY_STREQUENT); 372d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts_summary/strequent/filter/*", 373d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov CONTACTS_SUMMARY_STREQUENT_FILTER); 374d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts_summary/group/*", 375d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov CONTACTS_SUMMARY_GROUP); 376d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 37731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 3785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 3795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 3805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 3815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/filter_email/*", 382b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov CONTACTS_FILTER_EMAIL); 383b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 3854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 386ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 387ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 388ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 3891f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 390ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 391ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 392ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 393ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 39435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 39535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 396a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 397b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 398b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 399b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 400b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 4014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 402bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "presence", PRESENCE); 403bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "presence/#", PRESENCE_ID); 4041f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 405c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 406c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 407c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 408c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 409c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/#", 410c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 411c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 412fec4e13316f2731d84394e5fa2f93af3febdc20cEvan Millar HashMap<String, String> columns; 4134f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 414d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // Contacts projection map 4156bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov columns = new HashMap<String, String>(); 416d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts._ID, "contacts._id AS _id"); 417d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.DISPLAY_NAME, ContactsColumns.CONCRETE_DISPLAY_NAME + " AS " 418d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.DISPLAY_NAME); 419d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.LAST_TIME_CONTACTED, ContactsColumns.CONCRETE_LAST_TIME_CONTACTED 420d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " AS " + Contacts.LAST_TIME_CONTACTED); 421d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.TIMES_CONTACTED, ContactsColumns.CONCRETE_TIMES_CONTACTED + " AS " 422d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.TIMES_CONTACTED); 423d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.STARRED, ContactsColumns.CONCRETE_STARRED + " AS " 424d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED); 425d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 426d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 427d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.PRIMARY_PHONE_ID, Contacts.PRIMARY_PHONE_ID); 428d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.PRIMARY_EMAIL_ID, Contacts.PRIMARY_EMAIL_ID); 429d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.CUSTOM_RINGTONE, ContactsColumns.CONCRETE_CUSTOM_RINGTONE + " AS " 430d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.CUSTOM_RINGTONE); 431d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.SEND_TO_VOICEMAIL, ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL 432d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " AS " + Contacts.SEND_TO_VOICEMAIL); 433d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(ContactsColumns.FALLBACK_PRIMARY_PHONE_ID, 434d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.FALLBACK_PRIMARY_PHONE_ID); 435d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(ContactsColumns.FALLBACK_PRIMARY_EMAIL_ID, 436d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.FALLBACK_PRIMARY_EMAIL_ID); 437d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sContactsProjectionMap = columns; 4386bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 4391f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey columns = new HashMap<String, String>(); 440d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.putAll(sContactsProjectionMap); 441c62855331805c2744a097ef6ea625652197bfb87Dmitri Plotnikov 442d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // Contacts primaries projection map. The overall presence status is 443c62855331805c2744a097ef6ea625652197bfb87Dmitri Plotnikov // the most-present value, as indicated by the largest value. 44400ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey columns.put(Contacts.PRESENCE_STATUS, "MAX(" + Presence.PRESENCE_STATUS + ") AS " 44500ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey + Contacts.PRESENCE_STATUS); 446d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.PRIMARY_PHONE_TYPE, CommonDataKinds.Phone.TYPE); 447d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.PRIMARY_PHONE_LABEL, CommonDataKinds.Phone.LABEL); 448d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.PRIMARY_PHONE_NUMBER, CommonDataKinds.Phone.NUMBER); 449d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sContactsSummaryProjectionMap = columns; 45000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 4516cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts projection map 4524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton columns = new HashMap<String, String>(); 4535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov columns.put(RawContacts._ID, Tables.RAW_CONTACTS + "." + RawContacts._ID + " AS _id"); 454d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 4556cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov columns.put(RawContacts.ACCOUNT_NAME, 4565ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov OpenHelper.RawContactsColumns.CONCRETE_ACCOUNT_NAME 4575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " AS " + RawContacts.ACCOUNT_NAME); 4586cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov columns.put(RawContacts.ACCOUNT_TYPE, 4595ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov OpenHelper.RawContactsColumns.CONCRETE_ACCOUNT_TYPE 4605ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " AS " + RawContacts.ACCOUNT_TYPE); 4616cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov columns.put(RawContacts.SOURCE_ID, 4625ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov OpenHelper.RawContactsColumns.CONCRETE_SOURCE_ID 4635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " AS " + RawContacts.SOURCE_ID); 4646cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov columns.put(RawContacts.VERSION, 4655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov OpenHelper.RawContactsColumns.CONCRETE_VERSION 4665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " AS " + RawContacts.VERSION); 4676cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov columns.put(RawContacts.DIRTY, 4685ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov OpenHelper.RawContactsColumns.CONCRETE_DIRTY 4695ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " AS " + RawContacts.DIRTY); 47033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov columns.put(RawContacts.DELETED, 4715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov OpenHelper.RawContactsColumns.CONCRETE_DELETED 4725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " AS " + RawContacts.DELETED); 4733cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(RawContacts.TIMES_CONTACTED, 4743cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Tables.RAW_CONTACTS + "." + RawContacts.TIMES_CONTACTED 4753cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov + " AS " + People.TIMES_CONTACTED); 4763cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(RawContacts.LAST_TIME_CONTACTED, 4773cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Tables.RAW_CONTACTS + "." + RawContacts.LAST_TIME_CONTACTED 4783cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov + " AS " + People.LAST_TIME_CONTACTED); 4793cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(RawContacts.CUSTOM_RINGTONE, 4803cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Tables.RAW_CONTACTS + "." + RawContacts.CUSTOM_RINGTONE 4813cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov + " AS " + People.CUSTOM_RINGTONE); 4823cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(RawContacts.SEND_TO_VOICEMAIL, 4833cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Tables.RAW_CONTACTS + "." + RawContacts.SEND_TO_VOICEMAIL 4843cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov + " AS " + People.SEND_TO_VOICEMAIL); 4853cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(RawContacts.STARRED, 4863cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Tables.RAW_CONTACTS + "." + RawContacts.STARRED 4873cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov + " AS " + People.STARRED); 4883cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE); 4893cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(RawContacts.SYNC1, 4903cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Tables.RAW_CONTACTS + "." + RawContacts.SYNC1 + " AS " + RawContacts.SYNC1); 4913cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(RawContacts.SYNC2, 4923cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Tables.RAW_CONTACTS + "." + RawContacts.SYNC2 + " AS " + RawContacts.SYNC2); 4933cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(RawContacts.SYNC3, 4943cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Tables.RAW_CONTACTS + "." + RawContacts.SYNC3 + " AS " + RawContacts.SYNC3); 4953cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(RawContacts.SYNC4, 4963cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov Tables.RAW_CONTACTS + "." + RawContacts.SYNC4 + " AS " + RawContacts.SYNC4); 497d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sRawContactsProjectionMap = columns; 4984f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 4992815f58f72f109790585931f601a63ddc02536a5Evan Millar columns = new HashMap<String, String>(); 5002815f58f72f109790585931f601a63ddc02536a5Evan Millar columns.putAll(sContactsProjectionMap); 5012815f58f72f109790585931f601a63ddc02536a5Evan Millar columns.putAll(sRawContactsProjectionMap); 5022815f58f72f109790585931f601a63ddc02536a5Evan Millar sRawContactsContactsProjectionMap = columns; 5032815f58f72f109790585931f601a63ddc02536a5Evan Millar 5044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Data projection map 5054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton columns = new HashMap<String, String>(); 5065ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov columns.put(Data._ID, Tables.DATA + "." + Data._ID + " AS _id"); 5075ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov columns.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 50867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Data.RES_PACKAGE, PackagesColumns.PACKAGE + " AS " + Data.RES_PACKAGE); 509508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey columns.put(Data.MIMETYPE, Data.MIMETYPE); 510c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar columns.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 511c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar columns.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 512f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana columns.put(Data.DATA_VERSION, Data.DATA_VERSION); 5137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA1, "data.data1 as data1"); 5147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA2, "data.data2 as data2"); 5157e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA3, "data.data3 as data3"); 5167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA4, "data.data4 as data4"); 5177e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA5, "data.data5 as data5"); 5187e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA6, "data.data6 as data6"); 5197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA7, "data.data7 as data7"); 5207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA8, "data.data8 as data8"); 5217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA9, "data.data9 as data9"); 5227e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA10, "data.data10 as data10"); 52367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Data.DATA11, "data.data11 as data11"); 52467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Data.DATA12, "data.data12 as data12"); 52567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Data.DATA13, "data.data13 as data13"); 52667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Data.DATA14, "data.data14 as data14"); 52767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Data.DATA15, "data.data15 as data15"); 5283cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Data.SYNC1, Tables.DATA + "." + Data.SYNC1 + " AS " + Data.SYNC1); 5293cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Data.SYNC2, Tables.DATA + "." + Data.SYNC2 + " AS " + Data.SYNC2); 5303cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Data.SYNC3, Tables.DATA + "." + Data.SYNC3 + " AS " + Data.SYNC3); 5313cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Data.SYNC4, Tables.DATA + "." + Data.SYNC4 + " AS " + Data.SYNC4); 53267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(GroupMembership.GROUP_SOURCE_ID, GroupsColumns.CONCRETE_SOURCE_ID + " AS " 53367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey + GroupMembership.GROUP_SOURCE_ID); 53420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 53520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // TODO: remove this projection 536d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Mappings used for backwards compatibility. 537d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar columns.put("number", Phone.NUMBER); 5389261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana sDataGroupsProjectionMap = columns; 539a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 5409261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // Data, groups and contacts projection map for joins. _id comes from the data table 541a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton columns = new HashMap<String, String>(); 542d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.putAll(sRawContactsProjectionMap); 5439261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.putAll(sDataGroupsProjectionMap); // _id will be replaced with the one from data 544d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Data.RAW_CONTACT_ID, DataColumns.CONCRETE_RAW_CONTACT_ID); 5450c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar sDataRawContactsGroupsProjectionMap = columns; 5469261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 5479261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // Data and contacts projection map for joins. _id comes from the data table 5489261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns = new HashMap<String, String>(); 5490c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar columns.putAll(sDataRawContactsGroupsProjectionMap); 5509261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.remove(GroupMembership.GROUP_SOURCE_ID); 5510c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar sDataRawContactsProjectionMap = columns; 5527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 553de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millar // Data and contacts projection map for joins. _id comes from the data table 554de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millar columns = new HashMap<String, String>(); 555d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.putAll(sContactsProjectionMap); 556d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.putAll(sRawContactsProjectionMap); // 5579261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.putAll(sDataGroupsProjectionMap); // _id will be replaced with the one from data 558d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Data.RAW_CONTACT_ID, DataColumns.CONCRETE_RAW_CONTACT_ID); 5590c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar sDataRawContactsGroupsContactProjectionMap = columns; 5609261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 5619261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // Data and contacts projection map for joins. _id comes from the data table 5629261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns = new HashMap<String, String>(); 5630c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar columns.putAll(sDataRawContactsGroupsContactProjectionMap); 5649261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.remove(GroupMembership.GROUP_SOURCE_ID); 5650c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar sDataRawContactsContactProjectionMap = columns; 566c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 567ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 568ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 569ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups._ID, "groups._id AS _id"); 570035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 571035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 5729261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 5739261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.DIRTY, Groups.DIRTY); 5749261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.VERSION, Groups.VERSION); 57567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.RES_PACKAGE, PackagesColumns.PACKAGE + " AS " + Groups.RES_PACKAGE); 576ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 57767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 578ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 5793cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYSTEM_ID, Groups.SYSTEM_ID); 5803cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.NOTES, Groups.NOTES); 5813cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYNC1, Tables.GROUPS + "." + Groups.SYNC1 + " AS " + Groups.SYNC1); 5823cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYNC2, Tables.GROUPS + "." + Groups.SYNC2 + " AS " + Groups.SYNC2); 5833cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYNC3, Tables.GROUPS + "." + Groups.SYNC3 + " AS " + Groups.SYNC3); 5843cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov columns.put(Groups.SYNC4, Tables.GROUPS + "." + Groups.SYNC4 + " AS " + Groups.SYNC4); 585ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 586ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5876cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts and groups projection map 588ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 589ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 590ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 591d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 592d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 593ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 594ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 595ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 596ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 597d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 598d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 599ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 600ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + " AND " + Clauses.HAS_PRIMARY_PHONE + ") AS " + Groups.SUMMARY_WITH_PHONES); 601ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 602ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 603ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 604b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 605b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 606b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 607b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 608d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(AggregationExceptions.CONTACT_ID, 609d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "raw_contacts1." + RawContacts.CONTACT_ID 610d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " AS " + AggregationExceptions.CONTACT_ID); 6115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID, AggregationExceptionColumns.RAW_CONTACT_ID2); 612b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 613b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 614373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov 615373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns = new HashMap<String, String>(); 616373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence._ID, Presence._ID); 617373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.RAW_CONTACT_ID, Presence.RAW_CONTACT_ID); 618373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.DATA_ID, Presence.DATA_ID); 619373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.IM_ACCOUNT, Presence.IM_ACCOUNT); 620373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.IM_HANDLE, Presence.IM_HANDLE); 621373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.IM_PROTOCOL, Presence.IM_PROTOCOL); 622373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.PRESENCE_STATUS, Presence.PRESENCE_STATUS); 623373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.PRESENCE_CUSTOM_STATUS, Presence.PRESENCE_CUSTOM_STATUS); 624373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov sPresenceProjectionMap = columns; 625373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov 626d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sNestedRawContactIdSelect = "SELECT " + Data.RAW_CONTACT_ID + " FROM " + Tables.DATA + " WHERE " 627c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + Data._ID + "=?"; 628c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar sNestedMimetypeSelect = "SELECT " + DataColumns.MIMETYPE_ID + " FROM " + Tables.DATA 629c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + " WHERE " + Data._ID + "=?"; 630d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sNestedContactIdSelect = "SELECT " + RawContacts.CONTACT_ID + " FROM " + Tables.RAW_CONTACTS 631d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " WHERE " + RawContacts._ID + "=(" + sNestedRawContactIdSelect + ")"; 6325ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov sNestedContactIdListSelect = "SELECT " + RawContacts._ID + " FROM " + Tables.RAW_CONTACTS 633d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " WHERE " + RawContacts.CONTACT_ID + "=(" + sNestedContactIdSelect + ")"; 634d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sSetPrimaryWhere = Data.RAW_CONTACT_ID + "=(" + sNestedRawContactIdSelect + ") AND " 635c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + DataColumns.MIMETYPE_ID + "=(" + sNestedMimetypeSelect + ")"; 6365ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov sSetSuperPrimaryWhere = Data.RAW_CONTACT_ID + " IN (" + sNestedContactIdListSelect + ") AND " 637c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + DataColumns.MIMETYPE_ID + "=(" + sNestedMimetypeSelect + ")"; 638d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sContactsInGroupSelect = ContactsColumns.CONCRETE_ID + " IN (SELECT " 639d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + RawContacts.CONTACT_ID + " FROM " + Tables.RAW_CONTACTS + " WHERE (" 6406cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID + " IN (SELECT " + Tables.DATA + "." 6415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + Data.RAW_CONTACT_ID + " FROM " + Tables.DATA_JOIN_MIMETYPES + " WHERE (" 642b67163a1088f09c59f324350662eb18772fac6b6Evan Millar + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE + "' AND " 643b67163a1088f09c59f324350662eb18772fac6b6Evan Millar + GroupMembership.GROUP_ROW_ID + "=(SELECT " + Tables.GROUPS + "." 644b67163a1088f09c59f324350662eb18772fac6b6Evan Millar + Groups._ID + " FROM " + Tables.GROUPS + " WHERE " + Groups.TITLE + "=?)))))"; 6454f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 6464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 6473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 6483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 6493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 6503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 6513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 6533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 6553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 6563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 6593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 6603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 6615ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 662e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 663e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 664e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 665e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 666e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov setIsPrimary(dataId); 667e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 668e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 6695ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixContactDisplayName(db, rawContactId); 670e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 6713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 6743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 6753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 6763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 6773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor cursor) { 6783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov throw new UnsupportedOperationException(); 6793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 6823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov long dataId = c.getLong(DataQuery.ID); 6835ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = c.getLong(DataQuery.RAW_CONTACT_ID); 6843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov boolean primary = c.getInt(DataQuery.IS_PRIMARY) != 0; 6853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=" + dataId, null); 6863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 6875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 6885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixContactDisplayName(db, rawContactId); 6893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 6913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 6945ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long newPrimaryId = findNewPrimaryDataId(db, rawContactId); 6953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (newPrimaryId != -1) { 6963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov ContactsProvider2.this.setIsPrimary(newPrimaryId); 6973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected long findNewPrimaryDataId(SQLiteDatabase db, long rawContactId) { 701e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 702e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 7035ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Cursor c = queryData(db, rawContactId); 7043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 705e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 706e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long dataId = c.getLong(DataQuery.ID); 707e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int type = c.getInt(DataQuery.DATA2); 708e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 709e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 710e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 711e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 7123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 7143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 7153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 716e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return primaryId; 717e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 718e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 719e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 720e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 721e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 722e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 723e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 724e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 7253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7275ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected Cursor queryData(SQLiteDatabase db, long rawContactId) { 7283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov // TODO Lookup integer mimetype IDs' instead of joining for speed 7295ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return db.query(DataQuery.TABLE, DataQuery.COLUMNS, Data.RAW_CONTACT_ID + "=" 7305ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + rawContactId + " AND " + MimetypesColumns.MIMETYPE + "='" + mMimetype + "'", 7313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov null, null, null, null); 7323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7345ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected void fixContactDisplayName(SQLiteDatabase db, long rawContactId) { 735e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (!sDisplayNamePriorities.containsKey(mMimetype)) { 736e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return; 737e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 738e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 7393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String bestDisplayName = null; 74067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Cursor c = db.query(DisplayNameQuery.TABLE, DisplayNameQuery.COLUMNS, 7415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId, null, null, null, null); 7423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 7433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov int maxPriority = -1; 7443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov while (c.moveToNext()) { 7453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String mimeType = c.getString(DisplayNameQuery.MIMETYPE); 7463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov boolean primary; 7473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String name; 7483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) { 7503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov name = c.getString(DisplayNameQuery.DISPLAY_NAME); 7513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov primary = true; 7523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 7533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov name = c.getString(DisplayNameQuery.DATA2); 7543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov primary = (c.getInt(DisplayNameQuery.IS_PRIMARY) != 0); 7553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (primary && name != null) { 7583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Integer priority = sDisplayNamePriorities.get(mimeType); 7593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (priority != null && priority > maxPriority) { 7603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov maxPriority = priority; 7613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov bestDisplayName = name; 7623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 7673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 7683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7705ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov ContactsProvider2.this.setDisplayName(rawContactId, bestDisplayName); 7713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 7753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 7773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 7783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 7823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final NameSplitter mNameSplitter; 7843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public StructuredNameRowHandler(NameSplitter nameSplitter) { 7863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 7873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mNameSplitter = nameSplitter; 7883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 7915ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 7923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov fixStructuredNameComponents(values); 7935ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return super.insert(db, rawContactId, values); 7943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 7973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor cursor) { 7983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov // TODO Parse the full name if it has changed and replace pre-existing piece parts. 7993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 8023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Parses the supplied display name, but only if the incoming values do not already contain 8033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * structured name parts. Also, if the display name is not provided, generate one by 8043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * concatenating first name and last name 8053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * 8063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * TODO see if the order of first and last names needs to be conditionally reversed for 8073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * some locales, e.g. China. 8083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 8093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private void fixStructuredNameComponents(ContentValues values) { 8103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String fullName = values.getAsString(StructuredName.DISPLAY_NAME); 8113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (!TextUtils.isEmpty(fullName) 8123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov && TextUtils.isEmpty(values.getAsString(StructuredName.PREFIX)) 8133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov && TextUtils.isEmpty(values.getAsString(StructuredName.GIVEN_NAME)) 8143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov && TextUtils.isEmpty(values.getAsString(StructuredName.MIDDLE_NAME)) 8153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov && TextUtils.isEmpty(values.getAsString(StructuredName.FAMILY_NAME)) 8163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov && TextUtils.isEmpty(values.getAsString(StructuredName.SUFFIX))) { 8173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 8183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mNameSplitter.split(name, fullName); 8193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.PREFIX, name.getPrefix()); 8213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.GIVEN_NAME, name.getGivenNames()); 8223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.MIDDLE_NAME, name.getMiddleName()); 8233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.FAMILY_NAME, name.getFamilyName()); 8243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.SUFFIX, name.getSuffix()); 8253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (TextUtils.isEmpty(fullName)) { 8283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String givenName = values.getAsString(StructuredName.GIVEN_NAME); 8293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String familyName = values.getAsString(StructuredName.FAMILY_NAME); 8303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (TextUtils.isEmpty(givenName)) { 8313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov fullName = familyName; 8323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else if (TextUtils.isEmpty(familyName)) { 8333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov fullName = givenName; 8343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 8353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov fullName = givenName + " " + familyName; 8363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (!TextUtils.isEmpty(fullName)) { 8393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.DISPLAY_NAME, fullName); 8403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 8463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 8483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 8493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 8513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 8523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 8533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 8543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 8575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 8583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov int type; 8593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String label; 8603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (values.containsKey(mTypeColumn)) { 8613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov type = values.getAsInteger(mTypeColumn); 8623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 8633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov type = BaseTypes.TYPE_CUSTOM; 8643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (values.containsKey(mLabelColumn)) { 8663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov label = values.getAsString(mLabelColumn); 8673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 8683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov label = null; 8693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (type != BaseTypes.TYPE_CUSTOM && label != null) { 8727a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException(mLabelColumn + " value can only be specified with " 8733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov + mTypeColumn + "=" + BaseTypes.TYPE_CUSTOM + "(custom)"); 8743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (type == BaseTypes.TYPE_CUSTOM && label == null) { 8777a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException(mLabelColumn + " value must be specified when " 8783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov + mTypeColumn + "=" + BaseTypes.TYPE_CUSTOM + "(custom)"); 8793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return super.insert(db, rawContactId, values); 8823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 8853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor cursor) { 8863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov // TODO read the data and check the constraint 8873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 8913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 8933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 8943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 8975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 8985ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long id = super.insert(db, rawContactId, values); 8995ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixContactDisplayName(db, rawContactId); 9003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return id; 9013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 9043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 9053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 9063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 9073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 9083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 9093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 9103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 914e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 915e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 916e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 917e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 918e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 919e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 920e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 9215ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 9225ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long id = super.insert(db, rawContactId, values); 9235ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixContactDisplayName(db, rawContactId); 924e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return id; 925e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 926e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 927e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 928e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 929e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 930e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 931e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 932e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 933e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 934e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 935e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 936e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 937e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 938e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 9393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 9403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 9423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 9433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 9465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 947e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 948e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 949e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String normalizedNumber = null; 950e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 951e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 952e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 953e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 954e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 9555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long id = super.insert(db, rawContactId, values); 9563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 957e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 9585ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 959e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, id); 960e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 961e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov db.insert(Tables.PHONE_LOOKUP, null, phoneValues); 962e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 9633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return id; 9653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 9683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 9693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 9703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 9713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 9723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 9733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 9743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 9753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 9763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 9773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 9783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 9793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 98453056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov private final ContactAggregationScheduler mAggregationScheduler; 9854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private OpenHelper mOpenHelper; 98631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 987a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov private ContactAggregator mContactAggregator; 9884097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 989f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 990a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 991a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 99220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 99320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 994a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov public ContactsProvider2() { 99553056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov this(new ContactAggregationScheduler()); 996a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 997a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 998a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 999a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Constructor for testing. 1000a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 100153056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov /* package */ ContactsProvider2(ContactAggregationScheduler scheduler) { 100253056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov mAggregationScheduler = scheduler; 1003a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 10044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 10054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 10064f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 1007b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey final Context context = getContext(); 100835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 100931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov mOpenHelper = getOpenHelper(context); 1010a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 1011a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mOpenHelper, this, mGlobalSearchSupport); 101253056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov mContactAggregator = new ContactAggregator(context, mOpenHelper, mAggregationScheduler); 1013a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1014d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 1015c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement = db.compileStatement( 1016c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar "UPDATE " + Tables.DATA + " SET " + Data.IS_PRIMARY 1017c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + "=(_id=?) WHERE " + sSetPrimaryWhere); 1018c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement = db.compileStatement( 1019c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar "UPDATE " + Tables.DATA + " SET " + Data.IS_SUPER_PRIMARY 1020c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + "=(_id=?) WHERE " + sSetSuperPrimaryWhere); 10215ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mLastTimeContactedUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 10226cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContacts.TIMES_CONTACTED + "=" + RawContacts.TIMES_CONTACTED + "+1," 1023d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + RawContacts.LAST_TIME_CONTACTED + "=? WHERE " + RawContacts.CONTACT_ID + "=?"); 1024a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 10255ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mContactDisplayNameUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 10266cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContactsColumns.DISPLAY_NAME + "=? WHERE " + RawContacts._ID + "=?"); 10273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 102828f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar mNameSplitter = new NameSplitter( 102928f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_prefixes), 103028f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_last_name_prefixes), 103128f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_suffixes), 103228f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_conjunctions)); 10334097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 10343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 10353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 1036e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 10373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 10383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 103967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 104067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 10413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 10423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 104367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 104467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL)); 10453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 10463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new StructuredNameRowHandler(mNameSplitter)); 10473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10483d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (isLegacyContactImportNeeded()) { 10493d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (!importLegacyContacts()) { 10503d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 10513d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 10523d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 10531f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return (db != null); 10544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 10554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 105631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 105731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov protected OpenHelper getOpenHelper(final Context context) { 105831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov return OpenHelper.getInstance(context); 105931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 106031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 10613d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected boolean isLegacyContactImportNeeded() { 10623d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 10633d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return prefs.getInt(PREF_CONTACTS_IMPORTED, 0) < PREF_CONTACTS_IMPORT_VERSION; 10643d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 10653d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 10663d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov private boolean importLegacyContacts() { 10673d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (importLegacyContacts(getLegacyContactImporter())) { 10683d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 10693d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Editor editor = prefs.edit(); 10703d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.putInt(PREF_CONTACTS_IMPORTED, PREF_CONTACTS_IMPORT_VERSION); 10713d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov editor.commit(); 10723d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 10733d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } else { 10743d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 10753d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 10763d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 10773d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 10783d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov protected LegacyContactImporter getLegacyContactImporter() { 10793d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return new LegacyContactImporter(getContext(), this); 10803d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 10813d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 10823d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* Visible for testing */ 10833d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov /* package */ boolean importLegacyContacts(LegacyContactImporter importer) { 10843d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(false); 10853d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov try { 10863d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov importer.importContacts(); 10873d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.setEnabled(true); 10883d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov mContactAggregator.run(); 10893d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return true; 10903d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } catch (Throwable e) { 10913d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov Log.e(TAG, "Legacy contact import failed", e); 10923d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov return false; 10933d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 10943d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 10953d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1096a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 1097a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov protected void finalize() throws Throwable { 1098a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov if (mContactAggregator != null) { 1099a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mContactAggregator.quit(); 1100a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1101a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1102a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov super.finalize(); 1103a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1104a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1105a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1106a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1107a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1108a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 1109a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mOpenHelper.wipeData(); 1110a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1111a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1112a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1113a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Called when a change has been made. 1114a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 1115a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param uri the uri that the change was made to 1116a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 1117a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private void onChange(Uri uri) { 1118a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null); 1119a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1120a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 11214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 11224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean isTemporary() { 11234f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return false; 11244f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 11254f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 11263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 11273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 11283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 11293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 11303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 11313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 11333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 11343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 11354f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 11364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Uri insert(Uri uri, ContentValues values) { 1137a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 1138a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 113935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1140a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 114135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 114235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana id = mOpenHelper.getSyncState().insert(mOpenHelper.getWritableDatabase(), values); 114335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 114435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1145d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 1146d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 11476bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 11486bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 11496bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 11505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 1151f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana final Account account = readAccountFromQueryParams(uri); 1152d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov id = insertRawContact(values, account); 1153a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1154a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1155a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 11565ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 11575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 1158035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana id = insertData(values); 1159a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1160a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1161a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1162a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 1163035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana id = insertData(values); 1164a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1165a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1166a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1167ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 1168ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final Account account = readAccountFromQueryParams(uri); 1169ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey id = insertGroup(values, account); 1170ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1171ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1172ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 11731f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey case PRESENCE: { 11741f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey id = insertPresence(values); 11751f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 11761f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 11771f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1178a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 1179f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 1180a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1181a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 11827e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 11837e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 11847e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 11857e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 11867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final Uri result = ContentUris.withAppendedId(uri, id); 1187a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton onChange(result); 1188a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return result; 1189a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1190a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1191a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1192035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * If account is non-null then store it in the values. If the account is already 1193035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * specified in the values then it must be consistent with the account, if it is non-null. 1194035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param values the ContentValues to read from and update 1195035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param account the explicitly provided Account 1196035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @return false if the accounts are inconsistent 11977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 1198035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private boolean resolveAccount(ContentValues values, Account account) { 1199035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana // If either is specified then both must be specified. 12006cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = values.getAsString(RawContacts.ACCOUNT_NAME); 12016cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 1202035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName) || !TextUtils.isEmpty(accountType)) { 1203035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final Account valuesAccount = new Account(accountName, accountType); 1204035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null && !valuesAccount.equals(account)) { 1205035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return false; 1206035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1207035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana account = valuesAccount; 1208035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1209035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null) { 12106cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, account.mName); 12116cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, account.mType); 1212035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1213035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return true; 12147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 12157e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 12167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 1217d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 12186bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 12196bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 12206bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 12216bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 1222d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 1223a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov throw new UnsupportedOperationException("Aggregates are created automatically"); 12246bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 12256bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 12266bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 1227a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 1228a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 1229a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 1230f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana * @param account the account this contact should be associated with. may be null. 1231a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 1232a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 1233d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertRawContact(ContentValues values, Account account) { 12346bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /* 12356bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * The contact record is inserted in the contacts table, but it needs to 12366bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * be processed by the aggregator before it will be returned by the 12376bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * "aggregates" queries. 12386bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 1239a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 12406bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 1241a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov ContentValues overriddenValues = new ContentValues(values); 1242d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov overriddenValues.putNull(RawContacts.CONTACT_ID); 1243f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana if (!resolveAccount(overriddenValues, account)) { 12447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return -1; 12457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 12467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 12473d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov if (values.containsKey(RawContacts.DELETED) 12483d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov && values.getAsInteger(RawContacts.DELETED) != 0) { 12493d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov overriddenValues.put(RawContacts.AGGREGATION_MODE, 12503d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov RawContacts.AGGREGATION_MODE_DISABLED); 12513d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov } 12523d8b043c3341a5b6c2e781b7eba9767d5cd13267Dmitri Plotnikov 1253c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return db.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, overriddenValues); 1254a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1255a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1256a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1257a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 1258a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 1259a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 1260a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 1261a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 1262035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private long insertData(ContentValues values) { 12636cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov int aggregationMode = RawContacts.AGGREGATION_MODE_DISABLED; 1264a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1265a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 1266a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 1267a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton db.beginTransaction(); 1268a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton try { 126920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 127020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 127120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 12725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 1273a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 127467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey // Replace package with internal mapping 127520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 127667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 127720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 127867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 127920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 128067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 1281619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Replace mimetype with internal mapping 128220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 128320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 12847a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException(Data.MIMETYPE + " is required"); 128520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 128620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 128720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mOpenHelper.getMimeTypeId(mimeType)); 128820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 1289508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 1290321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana resolveGroupSourceIdInValues(rawContactId, mimeType, db, mValues, true /* isInsert */); 12914097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 12925ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov id = getDataRowHandler(mimeType).insert(db, rawContactId, mValues); 1293a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 12945ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov aggregationMode = mContactAggregator.markContactForAggregation(rawContactId); 1295a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1296a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton db.setTransactionSuccessful(); 1297a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } finally { 1298a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton db.endTransaction(); 1299a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1300a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1301f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov triggerAggregation(id, aggregationMode); 1302a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 13034f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 13044f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 13055ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void triggerAggregation(long rawContactId, int aggregationMode) { 1306f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 13076cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: 1308f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov mContactAggregator.schedule(); 1309f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 1310f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 13116cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_IMMEDITATE: 13125ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mContactAggregator.aggregateContact(rawContactId); 1313f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 1314f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 13156cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 1316f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov // Do nothing 1317f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 1318f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 1319f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 1320f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 1321a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 13225ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 13239261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 13249261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 13255ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 13269261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 13279261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 13289261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 13299261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 13309261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 13315ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId) { 13329261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Account account = null; 13336cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Cursor c = db.query(ContactsQuery.TABLE, ContactsQuery.PROJECTION, RawContacts._ID + "=" 13345ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + rawContactId, null, null, null, null); 13359261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 13369261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 133767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountName = c.getString(ContactsQuery.ACCOUNT_NAME); 133867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountType = c.getString(ContactsQuery.ACCOUNT_TYPE); 13399261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 13409261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana account = new Account(accountName, accountType); 13419261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 13429261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 13439261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 13449261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 13459261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 13469261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 13479261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 13489261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "has a sourceid the the contact must be associate with " 13499261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 13509261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 13519261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 13529261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 13535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 13546cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 13559261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 13569261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana new String[]{sourceId, account.mName, account.mType}, null, null, null); 13579261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 13589261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 13599261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return c.getLong(0); 13609261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 13619261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 13629261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.mName); 13639261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.mType); 13649261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 13659261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 13669261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 13679261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 13689261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 13699261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 13709261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return groupId; 13719261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 13729261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 13739261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 13749261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 13759261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 13769261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 13779261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 137820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 137920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 138020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private int deleteData(String selection, String[] selectionArgs) { 138120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 138220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 138320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov db.beginTransaction(); 138420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 138520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 138620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 138720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 138820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataIdQuery.COLUMNS, selection, selectionArgs, null); 138920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 139020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov while(c.moveToNext()) { 139120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov long dataId = c.getLong(DataIdQuery._ID); 139220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov count += deleteData(dataId); 139320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 139420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 139520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 139620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 139720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov db.setTransactionSuccessful(); 139820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 139920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov db.endTransaction(); 140020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 140120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 140220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 140320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 140420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 140520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 140620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 140720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov Cursor c = db.query(DataQuery.TABLE, DataQuery.COLUMNS, 140820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov DataColumns.CONCRETE_ID + "=" + dataId, null, null, null, null); 140920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // TODO apply restrictions 141020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 141120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 141220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 141320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 141420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 141520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String mimeType = c.getString(DataQuery.MIMETYPE); 141620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 141720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 141820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 141920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 142020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 142120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 142220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 142320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 142420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 14257a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana throw new IllegalArgumentException("Data type mismatch: expected " 142620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 142720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 142820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 142920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return getDataRowHandler(mimeType).delete(db, c); 143020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 143120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 143220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 143320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 143420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 143520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 1436d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Delete the given {@link Data} row, fixing up any {@link Contacts} 1437ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * primaries that reference it. 1438ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 1439ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private int deleteData(long dataId) { 1440ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 1441ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1442ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final long mimePhone = mOpenHelper.getMimeTypeId(Phone.CONTENT_ITEM_TYPE); 1443ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final long mimeEmail = mOpenHelper.getMimeTypeId(Email.CONTENT_ITEM_TYPE); 1444ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1445ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Check to see if the data about to be deleted was a super-primary on 1446ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // the parent aggregate, and set flags to fix-up once deleted. 1447ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long aggId = -1; 1448ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long mimeId = -1; 1449ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey String dataRaw = null; 1450ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey boolean fixOptimal = false; 1451ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey boolean fixFallback = false; 1452ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1453ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Cursor cursor = null; 1454ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey try { 1455d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov cursor = db.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 145667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey DataColumns.CONCRETE_ID + "=" + dataId, null, null, null, null); 1457ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (cursor.moveToFirst()) { 1458d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov aggId = cursor.getLong(DataContactsQuery.CONTACT_ID); 1459d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov mimeId = cursor.getLong(DataContactsQuery.MIMETYPE_ID); 1460ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (mimeId == mimePhone) { 1461d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov dataRaw = cursor.getString(DataContactsQuery.PHONE_NUMBER); 1462d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov fixOptimal = (cursor.getLong(DataContactsQuery.OPTIMAL_PHONE_ID) == dataId); 1463d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov fixFallback = (cursor.getLong(DataContactsQuery.FALLBACK_PHONE_ID) == dataId); 1464ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } else if (mimeId == mimeEmail) { 1465d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov dataRaw = cursor.getString(DataContactsQuery.EMAIL_DATA); 1466d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov fixOptimal = (cursor.getLong(DataContactsQuery.OPTIMAL_EMAIL_ID) == dataId); 1467d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov fixFallback = (cursor.getLong(DataContactsQuery.FALLBACK_EMAIL_ID) == dataId); 1468ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1469ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1470ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } finally { 1471ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (cursor != null) { 1472ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor.close(); 1473ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor = null; 1474ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1475ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1476ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1477ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Delete the requested data item. 1478ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey int dataDeleted = db.delete(Tables.DATA, Data._ID + "=" + dataId, null); 1479ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1480ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Fix-up any super-primary values that are now invalid. 1481ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (fixOptimal || fixFallback) { 1482ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 1483ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final StringBuilder scoreClause = new StringBuilder(); 1484ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1485ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final String SCORE = "score"; 1486ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1487ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Build scoring clause that will first pick data items under the 1488ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // same aggregate that have identical values, otherwise fall back to 1489ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // normal primary scoring from the member contacts. 1490ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.append("(CASE WHEN "); 1491ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (mimeId == mimePhone) { 1492ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.append(Phone.NUMBER); 1493ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } else if (mimeId == mimeEmail) { 1494ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.append(Email.DATA); 1495ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1496ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.append("="); 1497ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey DatabaseUtils.appendEscapedSQLString(scoreClause, dataRaw); 1498ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.append(" THEN 2 ELSE " + Data.IS_PRIMARY + " END) AS " + SCORE); 1499ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1500ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final String[] PROJ_PRIMARY = new String[] { 1501ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey DataColumns.CONCRETE_ID, 15026cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.IS_RESTRICTED, 1503ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.toString(), 1504ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 1505ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1506ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final int COL_DATA_ID = 0; 1507ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final int COL_IS_RESTRICTED = 1; 150867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final int COL_SCORE = 2; 1509ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1510d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov cursor = db.query(Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS, PROJ_PRIMARY, 1511d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.CONCRETE_ID + "=" + aggId + " AND " + DataColumns.MIMETYPE_ID 1512ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + "=" + mimeId, null, null, null, SCORE); 1513ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1514ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (fixOptimal) { 1515ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey String colId = null; 151667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey String colIsRestricted = null; 1517ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (mimeId == mimePhone) { 1518d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov colId = ContactsColumns.OPTIMAL_PRIMARY_PHONE_ID; 1519d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov colIsRestricted = ContactsColumns.OPTIMAL_PRIMARY_PHONE_IS_RESTRICTED; 1520ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } else if (mimeId == mimeEmail) { 1521d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov colId = ContactsColumns.OPTIMAL_PRIMARY_EMAIL_ID; 1522d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov colIsRestricted = ContactsColumns.OPTIMAL_PRIMARY_EMAIL_IS_RESTRICTED; 1523ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1524ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1525ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Start by replacing with null, since fixOptimal told us that 1526ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // the previous aggregate values are bad. 1527ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.putNull(colId); 152867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey values.putNull(colIsRestricted); 1529ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1530ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // When finding a new optimal primary, we only care about the 1531ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // highest scoring value, regardless of source. 1532ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (cursor.moveToFirst()) { 1533ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final long newOptimal = cursor.getLong(COL_DATA_ID); 153467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final long newIsRestricted = cursor.getLong(COL_IS_RESTRICTED); 1535ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1536ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (newOptimal != 0) { 1537ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(colId, newOptimal); 1538ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 153967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (newIsRestricted != 0) { 154067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey values.put(colIsRestricted, newIsRestricted); 1541ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1542ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1543ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1544ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1545ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (fixFallback) { 1546ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey String colId = null; 1547ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (mimeId == mimePhone) { 1548d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov colId = ContactsColumns.FALLBACK_PRIMARY_PHONE_ID; 1549ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } else if (mimeId == mimeEmail) { 1550d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov colId = ContactsColumns.FALLBACK_PRIMARY_EMAIL_ID; 1551ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1552ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1553ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Start by replacing with null, since fixFallback told us that 1554ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // the previous aggregate values are bad. 1555ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.putNull(colId); 1556ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1557ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // The best fallback value is the highest scoring data item that 1558ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // hasn't been restricted. 1559ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor.moveToPosition(-1); 1560ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey while (cursor.moveToNext()) { 1561ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final boolean isRestricted = (cursor.getInt(COL_IS_RESTRICTED) == 1); 1562ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!isRestricted) { 1563ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(colId, cursor.getLong(COL_DATA_ID)); 1564ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1565ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1566ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1567ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1568ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1569d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // Push through any contact updates we have 1570ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (values.size() > 0) { 1571d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov db.update(Tables.CONTACTS, values, ContactsColumns.CONCRETE_ID + "=" + aggId, 1572ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey null); 1573ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1574ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1575ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1576ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return dataDeleted; 1577ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1578ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1579ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 1580ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 1581ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 1582ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private long insertGroup(ContentValues values, Account account) { 1583ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 1584ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1585ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContentValues overriddenValues = new ContentValues(values); 1586ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!resolveAccount(overriddenValues, account)) { 1587ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return -1; 1588ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1589ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1590ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 159167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String packageName = overriddenValues.getAsString(Groups.RES_PACKAGE); 159267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 159367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey overriddenValues.put(GroupsColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 159467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 159567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey overriddenValues.remove(Groups.RES_PACKAGE); 1596ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1597ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return db.insert(Tables.GROUPS, Groups.TITLE, overriddenValues); 1598ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1599ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1600ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 16011f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey * Inserts a presence update. 16021f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 160370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public long insertPresence(ContentValues values) { 16041f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 16051f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey final String handle = values.getAsString(Presence.IM_HANDLE); 16061f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey final String protocol = values.getAsString(Presence.IM_PROTOCOL); 16071f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (TextUtils.isEmpty(handle) || TextUtils.isEmpty(protocol)) { 16081f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey throw new IllegalArgumentException("IM_PROTOCOL and IM_HANDLE are required"); 16091f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 16101f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 16111f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // TODO: generalize to allow other providers to match against email 1612a01e50cb1a5dd21293f8a8fe43f3fe0bf6349164Jeff Sharkey boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == Integer.parseInt(protocol); 16131f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 161470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov StringBuilder selection = new StringBuilder(); 16151f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String[] selectionArgs; 16161f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (matchEmail) { 161770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov selection.append("(" + Clauses.WHERE_IM_MATCHES + ") OR (" 161870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov + Clauses.WHERE_EMAIL_MATCHES + ")"); 16191f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey selectionArgs = new String[] { protocol, handle, handle }; 16201f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 162170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov selection.append(Clauses.WHERE_IM_MATCHES); 16221f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey selectionArgs = new String[] { protocol, handle }; 16231f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 16241f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 162570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (values.containsKey(Presence.DATA_ID)) { 162670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov selection.append(" AND " + DataColumns.CONCRETE_ID + "=") 162770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov .append(values.getAsLong(Presence.DATA_ID)); 162870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 162970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 16305ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (values.containsKey(Presence.RAW_CONTACT_ID)) { 1631d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov selection.append(" AND " + DataColumns.CONCRETE_RAW_CONTACT_ID + "=") 16325ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov .append(values.getAsLong(Presence.RAW_CONTACT_ID)); 163370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 163470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 163500ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey selection.append(" AND ").append(getContactsRestrictions()); 163670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 16371f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey long dataId = -1; 16385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = -1; 163970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 16401f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 16411f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 164270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov cursor = db.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 164370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov selection.toString(), selectionArgs, null, null, null); 16441f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 164567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 16465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 16471f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 16481f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 16491f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 16501f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 16511f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 165231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 165331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 165431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 16551f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 16561f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 16571f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey values.put(Presence.DATA_ID, dataId); 16585ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Presence.RAW_CONTACT_ID, rawContactId); 16591f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 16601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // Insert the presence update 16611f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey long presenceId = db.replace(Tables.PRESENCE, null, values); 16621f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return presenceId; 16631f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 16641f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 16654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 16664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public int delete(Uri uri, String selection, String[] selectionArgs) { 1667508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 1668508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 1669508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 167035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 167135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana return mOpenHelper.getSyncState().delete(db, selection, selectionArgs); 167235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1673d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 1674d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 16756bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 1676d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // Remove references to the contact first 16776bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov ContentValues values = new ContentValues(); 1678d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.putNull(RawContacts.CONTACT_ID); 16795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov db.update(Tables.RAW_CONTACTS, values, 1680d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov RawContacts.CONTACT_ID + "=" + contactId, null); 16816bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 1682d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov return db.delete(Tables.CONTACTS, BaseColumns._ID + "=" + contactId, null); 16836bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 16846bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 16855ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 168633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov return deleteRawContact(uri); 1687508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 1688508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 168920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 169020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return deleteData(selection, selectionArgs); 169120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 169220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1693508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: { 1694508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 1695ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return deleteData(dataId); 1696ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1697ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1698ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 1699ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 1700ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final long groupMembershipMimetypeId = mOpenHelper 1701ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 1702ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey int groupsDeleted = db.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 1703ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey int dataDeleted = db.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 1704ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 1705ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + groupId, null); 1706ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey mOpenHelper.updateAllVisible(); 1707ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return groupsDeleted + dataDeleted; 1708508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 1709508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 17101f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey case PRESENCE: { 17111f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return db.delete(Tables.PRESENCE, null, null); 17121f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 17131f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1714508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey default: 17153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 1716508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 17174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 17184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 171933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov private int deleteRawContact(Uri uri) { 17207a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana final String flag = uri.getQueryParameter(RawContacts.DELETE_PERMANENTLY); 17217a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana final boolean permanently = flag != null && "true".equals(flag.toLowerCase()); 17227a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana final long rawContactId = ContentUris.parseId(uri); 17237a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana return deleteRawContact(rawContactId, permanently); 172433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 172533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 17265ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public int deleteRawContact(long rawContactId, boolean permanently) { 172733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 172833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 1729c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // TODO delete aggregation exceptions 1730c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov mOpenHelper.removeContactIfSingleton(rawContactId); 173133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov if (permanently) { 1732373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov db.delete(Tables.PRESENCE, Presence.RAW_CONTACT_ID + "=" + rawContactId, null); 17335ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return db.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 173433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 173533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov mValues.clear(); 173633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov mValues.put(RawContacts.DELETED, true); 1737c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 1738c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 17395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return updateRawContact(rawContactId, mValues, null, null); 174033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 174133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 174233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 1743f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana private static Account readAccountFromQueryParams(Uri uri) { 17446cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String name = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 17456cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String type = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 1746f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana if (TextUtils.isEmpty(name) || TextUtils.isEmpty(type)) { 1747f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana return null; 1748f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana } 1749f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana return new Account(name, type); 1750f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana } 1751f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana 1752ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 17534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 17544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 175500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 175635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 175700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 175800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 175900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 176035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 176135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana return mOpenHelper.getSyncState().update(db, values, selection, selectionArgs); 176235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1763d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // TODO(emillar): We will want to disallow editing the contacts table at some point. 1764d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 1765d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov count = db.update(Tables.CONTACTS, values, selection, selectionArgs); 176600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 176700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 176800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 1769d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 1770d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov count = updateContactData(db, ContentUris.parseId(uri), values); 1771c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 1772c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 1773c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 177420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 1775321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana count = updateData(uri, values, selection, selectionArgs); 177620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 177720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 1778c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 177920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA_ID: { 1780321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana count = updateData(uri, values, selection, selectionArgs); 178100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 178200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 17837e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17845ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 17855ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov count = db.update(Tables.RAW_CONTACTS, values, selection, selectionArgs); 17867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 17877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17895ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 179033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 179133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov count = updateRawContact(rawContactId, values, selection, selectionArgs); 17927e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 17937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 1795ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 1796ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey count = db.update(Tables.GROUPS, values, selection, selectionArgs); 1797ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey mOpenHelper.updateAllVisible(); 1798ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1799ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1800ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1801ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 1802ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 1803ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey String selectionWithId = (Groups._ID + "=" + groupId + " ") 1804ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + (selection == null ? "" : " AND " + selection); 1805ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey count = db.update(Tables.GROUPS, values, selectionWithId, selectionArgs); 1806ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1807d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // If changing visibility, then update contacts 1808ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (values.containsKey(Groups.GROUP_VISIBLE)) { 1809ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey mOpenHelper.updateAllVisible(); 1810ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1811ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1812ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1813ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1814ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1815127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 1816127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov count = updateAggregationException(db, values); 1817b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 1818b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 1819b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 18207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana default: 1821f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 182200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 182300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 182400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar if (count > 0) { 182500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar getContext().getContentResolver().notifyChange(uri, null); 182600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 182700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 18284f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 18294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 18305ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private int updateRawContact(long rawContactId, ContentValues values, String selection, 183133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov String[] selectionArgs) { 183233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 18335ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov String selectionWithId = (RawContacts._ID + " = " + rawContactId + " ") 183433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov + (selection == null ? "" : " AND " + selection); 18355ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return db.update(Tables.RAW_CONTACTS, values, selectionWithId, selectionArgs); 183633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 183733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 1838321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(Uri uri, ContentValues values, String selection, 183920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String[] selectionArgs) { 184020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 184120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 184220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov db.beginTransaction(); 184320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 184420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 184520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 1846321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana Cursor c = query(uri, DataIdQuery.COLUMNS, selection, selectionArgs, null); 184720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 184820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov while(c.moveToNext()) { 1849321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana final long dataId = c.getLong(DataIdQuery._ID); 1850321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana final long rawContactId = c.getLong(DataIdQuery.RAW_CONTACT_ID); 1851321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana final String mimetype = c.getString(DataIdQuery.MIMETYPE); 1852321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana count += updateData(dataId, rawContactId, mimetype, values); 185320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 185420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 185520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 185620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 185720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov db.setTransactionSuccessful(); 185820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 185920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov db.endTransaction(); 186020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 186120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 186220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 186320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 186420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1865321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private int updateData(long dataId, long rawContactId, String mimeType, ContentValues values) { 186620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 186720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 186820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 186920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 187020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 18715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 187220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 187320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 187420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 187520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 187620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 187720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 187820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 187920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 188070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 188170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 188220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 188320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 188420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 188570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 188620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 188770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 188820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 188970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 189020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 189170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 189220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 189320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 189420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (containsIsSuperPrimary) { 189520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov setIsSuperPrimary(dataId); 189620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov setIsPrimary(dataId); 189720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 189820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 189970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 190020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (containsIsPrimary) { 190170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 190220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 190320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } else if (containsIsPrimary) { 190420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov setIsPrimary(dataId); 190520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 190620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 190770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 190820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 190920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1910321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana resolveGroupSourceIdInValues(rawContactId, mimeType, db, mValues, false /* isInsert */); 1911321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 191270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (mValues.size() > 0) { 191370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return db.update(Tables.DATA, mValues, Data._ID + " = " + dataId, null); 191420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 191520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 191620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 191720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1918321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana private void resolveGroupSourceIdInValues(long rawContactId, String mimeType, SQLiteDatabase db, 1919321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana ContentValues values, boolean isInsert) { 1920321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana if (GroupMembership.CONTENT_ITEM_TYPE.equals(mimeType)) { 1921321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID); 1922321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID); 1923321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana if (containsGroupSourceId && containsGroupId) { 1924321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana throw new IllegalArgumentException( 1925321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 1926321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana + "and GroupMembership.GROUP_ROW_ID"); 1927321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 1928321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 1929321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana if (!containsGroupSourceId && !containsGroupId) { 1930321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana if (isInsert) { 1931321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana throw new IllegalArgumentException( 1932321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 1933321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana + "and GroupMembership.GROUP_ROW_ID"); 1934321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } else { 1935321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana return; 1936321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 1937321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 1938321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 1939321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana if (containsGroupSourceId) { 1940321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID); 1941321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana final long groupId = getOrMakeGroup(db, rawContactId, sourceId); 1942321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana values.remove(GroupMembership.GROUP_SOURCE_ID); 1943321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana values.put(GroupMembership.GROUP_ROW_ID, groupId); 1944321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 1945321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 1946321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana } 1947321afd997c985f150a13e0a5538e2a12b755b217Fred Quintana 1948d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private int updateContactData(SQLiteDatabase db, long contactId, ContentValues values) { 1949d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1950d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // First update all constituent contacts 1951f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov ContentValues optionValues = new ContentValues(5); 19526cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov OpenHelper.copyStringValue(optionValues, RawContacts.CUSTOM_RINGTONE, 1953d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 19546cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov OpenHelper.copyLongValue(optionValues, RawContacts.SEND_TO_VOICEMAIL, 1955d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 19566cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov OpenHelper.copyLongValue(optionValues, RawContacts.LAST_TIME_CONTACTED, 1957d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 19586cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov OpenHelper.copyLongValue(optionValues, RawContacts.TIMES_CONTACTED, 1959d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 19606cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov OpenHelper.copyLongValue(optionValues, RawContacts.STARRED, 1961d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 1962d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1963d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 1964d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov if (optionValues.size() == 0) { 1965d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 1966d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 1967d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 19685ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov db.update(Tables.RAW_CONTACTS, optionValues, 1969d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov RawContacts.CONTACT_ID + "=" + contactId, null); 1970d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov return db.update(Tables.CONTACTS, values, Contacts._ID + "=" + contactId, null); 1971f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 1972d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1973d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public void updateContactTime(long contactId, long lastTimeContacted) { 1974f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov mLastTimeContactedUpdate.bindLong(1, lastTimeContacted); 1975d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov mLastTimeContactedUpdate.bindLong(2, contactId); 1976f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov mLastTimeContactedUpdate.execute(); 1977d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 1978d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 19795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static class RawContactPair { 19805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov final long rawContactId1; 19815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov final long rawContactId2; 1982127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 1983127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov /** 19845ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Constructor that ensures that this.rawContactId1 < this.rawContactId2 1985127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov */ 19865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public RawContactPair(long rawContactId1, long rawContactId2) { 19875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (rawContactId1 < rawContactId2) { 19885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov this.rawContactId1 = rawContactId1; 19895ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov this.rawContactId2 = rawContactId2; 1990127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } else { 19915ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov this.rawContactId2 = rawContactId1; 19925ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov this.rawContactId1 = rawContactId2; 1993127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 1994127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 1995127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 199680c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 1997127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 1998127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 1999d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = values.getAsInteger(AggregationExceptions.CONTACT_ID); 20005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID); 200180c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 20023cfe8d532d509fbbe605454e3a32b2361b7e1501Dmitri Plotnikov // First, we build a list of rawContactID-rawContactID pairs for the given contact. 20035ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov ArrayList<RawContactPair> pairs = new ArrayList<RawContactPair>(); 2004d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Cursor c = db.query(ContactsQuery.TABLE, ContactsQuery.PROJECTION, RawContacts.CONTACT_ID 2005d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + "=" + contactId, null, null, null, null); 2006127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov try { 2007127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov while (c.moveToNext()) { 20085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long aggregatedContactId = c.getLong(ContactsQuery.RAW_CONTACT_ID); 20095ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (aggregatedContactId != rawContactId) { 20105ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov pairs.add(new RawContactPair(aggregatedContactId, rawContactId)); 2011e2e0ba75ce239f0f5481cdef9082daebf8fc2d35Dmitri Plotnikov } 2012b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2013b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } finally { 2014b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov c.close(); 2015b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2016127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 2017127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // Now we iterate through all contact pairs to see if we need to insert/delete/update 2018127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // the corresponding exception 2019127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 2020127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 20215ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov for (RawContactPair pair : pairs) { 2022127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov final String whereClause = 20235ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov AggregationExceptionColumns.RAW_CONTACT_ID1 + "=" + pair.rawContactId1 + " AND " 20245ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + AggregationExceptionColumns.RAW_CONTACT_ID2 + "=" + pair.rawContactId2; 2025127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 2026127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, whereClause, null); 2027127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } else { 20285ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov exceptionValues.put(AggregationExceptionColumns.RAW_CONTACT_ID1, pair.rawContactId1); 20295ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov exceptionValues.put(AggregationExceptionColumns.RAW_CONTACT_ID2, pair.rawContactId2); 2030127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 2031127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov exceptionValues); 2032127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 2033127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 2034127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 20355ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov int aggregationMode = mContactAggregator.markContactForAggregation(rawContactId); 20366cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov if (aggregationMode != RawContacts.AGGREGATION_MODE_DISABLED) { 20375ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId); 2038f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC 2039f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov || exceptionType == AggregationExceptions.TYPE_KEEP_OUT) { 2040d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 2041f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 20427a39bf269294a8130ddd463460b9b36cf4ff74a8Dmitri Plotnikov } 2043127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 2044127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 2045127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 2046127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 2047b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2048b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 2049619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 2050619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Test if a {@link String} value appears in the given list. 2051619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 2052619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private boolean isContained(String[] array, String value) { 2053bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar if (array != null) { 2054bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar for (String test : array) { 2055bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar if (value.equals(test)) { 2056bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar return true; 2057bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar } 2058619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2059619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2060619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey return false; 2061619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2062619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2063619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 2064619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Test if a {@link String} value appears in the given list, and add to the 2065619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * array if the value doesn't already appear. 2066619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 2067619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private String[] assertContained(String[] array, String value) { 206800ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey if (array != null && !isContained(array, value)) { 2069619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey String[] newArray = new String[array.length + 1]; 2070619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey System.arraycopy(array, 0, newArray, 0, array.length); 2071619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey newArray[array.length] = value; 2072619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey array = newArray; 2073619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2074619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey return array; 2075619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2076619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 20774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 20784f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 20794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 20804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 208135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2082d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 20831f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 2084c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 2085c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2086d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov String contactIdColName = Tables.CONTACTS + "." + Contacts._ID; 20874f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2088619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 2089619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 2090a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 20914f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 209235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 209335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana return mOpenHelper.getSyncState().query(db, projection, selection, selectionArgs, 209435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 209535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 2096d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 2097d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.CONTACTS); 209800ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey applyContactsRestrictions(qb); 209900ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey applyContactsPrimaryRestrictions(sContactsProjectionMap); 2100d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 2101619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 2102619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2103619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2104d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2105619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey long aggId = ContentUris.parseId(uri); 2106d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.CONTACTS); 2107d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(ContactsColumns.CONCRETE_ID + "=" + aggId + " AND "); 210800ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey applyContactsRestrictions(qb); 210900ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey applyContactsPrimaryRestrictions(sContactsProjectionMap); 2110d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 21116bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 21126bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 21136bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 2114d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_SUMMARY: { 2115619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: join into social status tables 2116d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.CONTACTS_JOIN_PRESENCE_PRIMARY_PHONE); 211700ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey applyContactsRestrictions(qb); 211800ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey applyContactsPrimaryRestrictions(sContactsSummaryProjectionMap); 2119d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projection = assertContained(projection, Contacts.PRIMARY_PHONE_ID); 2120d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sContactsSummaryProjectionMap); 2121d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov groupBy = contactIdColName; 21221f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 21231f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 21241f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2125d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_SUMMARY_ID: { 2126619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: join into social status tables 21271f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey long aggId = ContentUris.parseId(uri); 2128d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.CONTACTS_JOIN_PRESENCE_PRIMARY_PHONE); 2129d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(ContactsColumns.CONCRETE_ID + "=" + aggId + " AND "); 213000ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey applyContactsRestrictions(qb); 213100ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey applyContactsPrimaryRestrictions(sContactsSummaryProjectionMap); 2132d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projection = assertContained(projection, Contacts.PRIMARY_PHONE_ID); 2133d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sContactsSummaryProjectionMap); 2134d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov groupBy = contactIdColName; 21351f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 21361f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 21371f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2138d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_SUMMARY_FILTER: { 2139619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: filter query based on callingUid 2140d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.CONTACTS_JOIN_PRESENCE_PRIMARY_PHONE); 2141d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sContactsSummaryProjectionMap); 2142ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 2143d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(buildContactLookupWhereClause(uri.getLastPathSegment())); 2144ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2145d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov groupBy = contactIdColName; 2146ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 2147ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2148ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 2149d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_SUMMARY_STREQUENT_FILTER: 2150d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_SUMMARY_STREQUENT: { 2151d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the first query for starred 2152d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.CONTACTS_JOIN_PRESENCE_PRIMARY_PHONE); 2153d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sContactsSummaryProjectionMap); 2154d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov if (match == CONTACTS_SUMMARY_STREQUENT_FILTER 2155d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 2156d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(buildContactLookupWhereClause(uri.getLastPathSegment())); 2157d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 2158d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov final String starredQuery = qb.buildQuery(projection, Contacts.STARRED + "=1", 2159d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov null, contactIdColName, null, null, 2160d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar null /* limit */); 2161d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 2162d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 2163d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 2164d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.CONTACTS_JOIN_PRESENCE_PRIMARY_PHONE); 2165d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sContactsSummaryProjectionMap); 2166d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov if (match == CONTACTS_SUMMARY_STREQUENT_FILTER 2167d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 2168d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(buildContactLookupWhereClause(uri.getLastPathSegment())); 2169d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 2170d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String frequentQuery = qb.buildQuery(projection, 2171d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 2172d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 2173d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov null, contactIdColName, null, null, null); 2174d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 2175d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 2176d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 2177d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 2178d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar Cursor c = db.rawQueryWithFactory(null, query, null, 2179d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Tables.CONTACTS_JOIN_PRESENCE_PRIMARY_PHONE); 2180d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 2181d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar if ((c != null) && !isTemporary()) { 2182d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 2183d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 2184d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 2185d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 2186d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 2187d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 2188d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_SUMMARY_GROUP: { 2189d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.CONTACTS_JOIN_PRESENCE_PRIMARY_PHONE); 219000ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey applyContactsRestrictions(qb); 219100ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey applyContactsPrimaryRestrictions(sContactsSummaryProjectionMap); 2192d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projection = assertContained(projection, Contacts.PRIMARY_PHONE_ID); 2193d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sContactsSummaryProjectionMap); 2194b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 2195d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(" AND " + sContactsInGroupSelect); 2196b67163a1088f09c59f324350662eb18772fac6b6Evan Millar selectionArgs = appendGroupArg(selectionArgs, uri.getLastPathSegment()); 2197b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 2198d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov groupBy = contactIdColName; 2199b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 2200b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 2201b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 2202d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_DATA: { 2203619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey long aggId = Long.parseLong(uri.getPathSegments().get(1)); 2204d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS_GROUPS); 2205d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(RawContacts.CONTACT_ID + "=" + aggId + " AND "); 2206619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyDataRestrictionExceptions(qb); 220700ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey applyContactsPrimaryRestrictions(sDataRawContactsGroupsContactProjectionMap); 220800ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey qb.setProjectionMap(sDataRawContactsGroupsContactProjectionMap); 22096bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 22106bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 221100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 22122815f58f72f109790585931f601a63ddc02536a5Evan Millar case CONTACTS_RAW_CONTACTS: { 22132815f58f72f109790585931f601a63ddc02536a5Evan Millar long contactId = Long.parseLong(uri.getPathSegments().get(1)); 22142815f58f72f109790585931f601a63ddc02536a5Evan Millar qb.setTables(Tables.RAW_CONTACTS_JOIN_CONTACTS); 22152815f58f72f109790585931f601a63ddc02536a5Evan Millar qb.setProjectionMap(sRawContactsContactsProjectionMap); 22162815f58f72f109790585931f601a63ddc02536a5Evan Millar qb.appendWhere(RawContacts.CONTACT_ID + "=" + contactId + " AND "); 22172815f58f72f109790585931f601a63ddc02536a5Evan Millar applyDataRestrictionExceptions(qb); 22182815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 22192815f58f72f109790585931f601a63ddc02536a5Evan Millar } 22202815f58f72f109790585931f601a63ddc02536a5Evan Millar 2221ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 2222d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS); 22230c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar qb.setProjectionMap(sDataRawContactsContactProjectionMap); 2224ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.appendWhere(Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 2225ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 2226d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(" AND " + buildContactLookupWhereClause( 2227ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar uri.getLastPathSegment())); 2228ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2229ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 2230ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2231ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2232ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES: { 2233d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS); 22340c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar qb.setProjectionMap(sDataRawContactsContactProjectionMap); 2235ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.appendWhere(Data.MIMETYPE + " = \"" + Phone.CONTENT_ITEM_TYPE + "\""); 2236ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 2237ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2238ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 2239ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 2240d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS); 22410c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar qb.setProjectionMap(sDataRawContactsContactProjectionMap); 224267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey qb.appendWhere(Data.MIMETYPE + " = \"" + StructuredPostal.CONTENT_ITEM_TYPE + "\""); 2243ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 2244ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2245ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 22465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 22475ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.setTables(Tables.RAW_CONTACTS); 2248d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sRawContactsProjectionMap); 224900ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey applyContactsRestrictions(qb); 22504f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 22514f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 22524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 22535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 22545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 22555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.setTables(Tables.RAW_CONTACTS); 2256d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sRawContactsProjectionMap); 22575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.appendWhere(RawContactsColumns.CONCRETE_ID + "=" + rawContactId + " AND "); 225800ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey applyContactsRestrictions(qb); 22594f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 22604f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 22614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 22625ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 22635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 22645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.setTables(Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_GROUPS); 22650c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar qb.setProjectionMap(sDataRawContactsGroupsProjectionMap); 22665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.appendWhere(Data.RAW_CONTACT_ID + "=" + rawContactId + " AND "); 2267619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyDataRestrictionExceptions(qb); 2268a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2269a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2270a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 227128ab0f857caa92402878244d9c5ea2a59e070935Jeff Sharkey case CONTACTS_FILTER_EMAIL: { 2272619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: filter query based on callingUid 2273d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS); 22740c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar qb.setProjectionMap(sDataRawContactsProjectionMap); 22755d0f923eb4c5351ebf323cc6f19c82acff98693eJeff Sharkey qb.appendWhere(Data.MIMETYPE + "='" + CommonDataKinds.Email.CONTENT_ITEM_TYPE + "'"); 2276e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey qb.appendWhere(" AND " + CommonDataKinds.Email.DATA + "="); 2277e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey qb.appendWhereEscapeString(uri.getPathSegments().get(2)); 2278e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 2279e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 2280e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 2281e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 22826cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 22836cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 2284343c56b5679c58bf1835a0e219fff57beae6ecefFred Quintana if (!TextUtils.isEmpty(accountName)) { 2285226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(RawContactsColumns.CONCRETE_ACCOUNT_NAME + "=" 2286035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 2287226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + "=" 2288035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountType) + " AND "); 2289343c56b5679c58bf1835a0e219fff57beae6ecefFred Quintana } 22905ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.setTables(Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_GROUPS); 22919261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana qb.setProjectionMap(sDataGroupsProjectionMap); 2292619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyDataRestrictionExceptions(qb); 2293e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 2294e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 2295e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 22964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 22975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.setTables(Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_GROUPS); 22989261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana qb.setProjectionMap(sDataGroupsProjectionMap); 2299ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.appendWhere(DataColumns.CONCRETE_ID + "=" + ContentUris.parseId(uri) + " AND "); 2300619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyDataRestrictionExceptions(qb); 23014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 23024f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 23034f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2304a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 2305619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: filter query based on callingUid 2306a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 2307a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 2308a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 23095ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov sortOrder = Data.RAW_CONTACT_ID; 2310a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2311a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2312a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final String number = uri.getLastPathSegment(); 2313bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov OpenHelper.buildPhoneLookupQuery(qb, number); 23140c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar qb.setProjectionMap(sDataRawContactsProjectionMap); 2315a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2316a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2317a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2318ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2319ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.GROUPS_JOIN_PACKAGES); 2320ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 2321ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2322ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2323ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2324ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2325ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 2326ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.GROUPS_JOIN_PACKAGES); 2327ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 2328ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.appendWhere(GroupsColumns.CONCRETE_ID + "=" + groupId); 2329ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2330ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2331ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2332ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 2333d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.GROUPS_JOIN_PACKAGES_DATA_RAW_CONTACTS_CONTACTS); 2334ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 2335ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey groupBy = GroupsColumns.CONCRETE_ID; 2336ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2337ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2338ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2339b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 23405ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS_JOIN_RAW_CONTACTS); 2341b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 2342b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 2343b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2344b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 234531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 2346d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 2347c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2348c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // TODO drop MAX_SUGGESTIONS in favor of LIMIT 234931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final String maxSuggestionsParam = 235031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov uri.getQueryParameter(AggregationSuggestions.MAX_SUGGESTIONS); 235131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 235231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 235331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (maxSuggestionsParam != null) { 235431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = Integer.parseInt(maxSuggestionsParam); 235531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 235631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 235731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 235831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 2359d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(contactId, projection, 2360d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sContactsProjectionMap, maxSuggestions); 236131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 236231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 23635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case PRESENCE: { 2364373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setTables(Tables.PRESENCE); 2365373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setProjectionMap(sPresenceProjectionMap); 23665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 23675ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 23685ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 23695ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case PRESENCE_ID: { 2370373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setTables(Tables.PRESENCE); 2371373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setProjectionMap(sPresenceProjectionMap); 2372373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.appendWhere(Presence._ID + "=" + ContentUris.parseId(uri)); 23735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 23745ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 23755ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 2376c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 2377a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 2378c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 2379c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2380c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 2381c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // TODO 2382c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov break; 2383c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 2384c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 23854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 2386f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 2387c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 23884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 23894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 23904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Perform the query and set the notification uri 23911f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey final Cursor c = qb.query(db, projection, selection, selectionArgs, 2392bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar groupBy, null, sortOrder, limit); 23934f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 23944f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 23954f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 23964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 23974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 23984f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 23997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 2400c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 2401c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 2402c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 2403c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 2404c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 2405c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private String getLimit(Uri url) { 2406c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limitParam = url.getQueryParameter("limit"); 2407c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 2408c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 2409c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 2410c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 2411c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 2412c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 2413c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 2414c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 2415c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 2416c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 2417c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 2418c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 2419c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 2420c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 2421c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 2422c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 2423c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2424c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov /** 24256cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov * List of package names with access to {@link RawContacts#IS_RESTRICTED} data. 242667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey */ 242767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final String[] sAllowedPackages = new String[] { 242867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey "com.android.contacts", 242967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey "com.facebook", 243067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey }; 243167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 243267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey /** 243367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey * Check if {@link Binder#getCallingUid()} should be allowed access to 24346cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov * {@link RawContacts#IS_RESTRICTED} data. 243567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey */ 243667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private boolean hasRestrictedAccess() { 243767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final PackageManager pm = getContext().getPackageManager(); 243867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String[] callerPackages = pm.getPackagesForUid(Binder.getCallingUid()); 243967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 244067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey // Has restricted access if caller matches any packages 244167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey for (String callerPackage : callerPackages) { 244267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey for (String allowedPackage : sAllowedPackages) { 244367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (allowedPackage.equals(callerPackage)) { 244467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey return true; 244567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 244667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 244767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 244867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey return false; 244967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 245067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 245167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey /** 2452619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Find any exceptions that have been granted to the calling process, and 2453d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * add projections to correctly select {@link Contacts#PRIMARY_PHONE_ID} 2454d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * and {@link Contacts#PRIMARY_EMAIL_ID}. 2455619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 245600ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey private void applyContactsPrimaryRestrictions(HashMap<String, String> projection) { 245767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey String projectionPhone; 245867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey String projectionEmail; 245967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 246067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (hasRestrictedAccess()) { 246167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey // With restricted access, always give optimal values 2462d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projectionPhone = ContactsColumns.OPTIMAL_PRIMARY_PHONE_ID + " AS " 2463d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.PRIMARY_PHONE_ID; 2464d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projectionEmail = ContactsColumns.OPTIMAL_PRIMARY_EMAIL_ID + " AS " 2465d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.PRIMARY_EMAIL_ID; 246667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 246767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey // With general access, always give fallback values 2468d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projectionPhone = ContactsColumns.FALLBACK_PRIMARY_PHONE_ID + " AS " 2469d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.PRIMARY_PHONE_ID; 2470d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projectionEmail = ContactsColumns.FALLBACK_PRIMARY_EMAIL_ID + " AS " 2471d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.PRIMARY_EMAIL_ID; 247267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 247367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2474d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projection.remove(Contacts.PRIMARY_PHONE_ID); 2475d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projection.put(Contacts.PRIMARY_PHONE_ID, projectionPhone); 2476619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2477d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projection.remove(Contacts.PRIMARY_EMAIL_ID); 2478d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projection.put(Contacts.PRIMARY_EMAIL_ID, projectionEmail); 2479619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2480619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2481619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 248200ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey * Restrict selection of {@link Contacts} to only public ones, or those 248300ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey * the caller has been granted an exception to. 2484619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 248500ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey private void applyContactsRestrictions(SQLiteQueryBuilder qb) { 248600ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey qb.appendWhere(getContactsRestrictions()); 248770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 248870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 248900ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey String getContactsRestrictions() { 249067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (hasRestrictedAccess()) { 249170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 249270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 24936cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov return RawContacts.IS_RESTRICTED + "=0"; 249470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 249570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 249670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 249770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 249870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (hasRestrictedAccess()) { 249970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 250067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 25015ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 25025ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 2503619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2504619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2505619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2506619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 2507619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Find any exceptions that have been granted to the 2508619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * {@link Binder#getCallingUid()}, and add a limiting clause to the given 2509619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * {@link SQLiteQueryBuilder} to hide restricted data. 2510619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 2511e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov void applyDataRestrictionExceptions(SQLiteQueryBuilder qb) { 251200ec508630251d6c6e3746469c9428f5a8cd5996Jeff Sharkey applyContactsRestrictions(qb); 2513619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2514619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2515619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 25167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 25177e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 25187e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 25197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static class ContactsEntityIterator implements EntityIterator { 25207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private final Cursor mEntityCursor; 25217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private volatile boolean mIsClosed; 25227e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25237e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] DATA_KEYS = new String[]{ 25247a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 25257a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 25267a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 25277a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 25287a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 25297a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 25307a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 25317a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 25327a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 25337a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 25347a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 25357a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 25367a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 25377a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 25387a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 25397a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 25407a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 25417a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 25427a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4}; 25437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] PROJECTION = new String[]{ 25456cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 25466cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 25476cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.SOURCE_ID, 25486cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.VERSION, 25496cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.DIRTY, 25507a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data._ID, 25517a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.RES_PACKAGE, 25527a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.MIMETYPE, 25537a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA1, 25547a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA2, 25557a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA3, 25567a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA4, 25577a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA5, 25587a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA6, 25597a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA7, 25607a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA8, 25617a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA9, 25627a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA10, 25637a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA11, 25647a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA12, 25657a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA13, 25667a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA14, 25677a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA15, 25687a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC1, 25697a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC2, 25707a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC3, 25717a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.SYNC4, 25727a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.RAW_CONTACT_ID, 25737a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.IS_PRIMARY, 25747a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Data.DATA_VERSION, 25757a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana GroupMembership.GROUP_SOURCE_ID, 25767a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC1, 25777a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC2, 25787a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC3, 25797a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana RawContacts.SYNC4}; 2580035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana 2581035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_NAME = 0; 2582035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_TYPE = 1; 2583035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_SOURCE_ID = 2; 2584035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_VERSION = 3; 2585035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DIRTY = 4; 2586035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DATA_ID = 5; 258767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_RES_PACKAGE = 6; 258867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_MIMETYPE = 7; 258967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_DATA1 = 8; 25907a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_RAW_CONTACT_ID = 27; 25917a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_IS_PRIMARY = 28; 25927a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_DATA_VERSION = 29; 25937a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_GROUP_SOURCE_ID = 30; 25947a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC1 = 31; 25957a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC2 = 32; 25967a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC3 = 33; 25977a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC4 = 34; 25987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public ContactsEntityIterator(ContactsProvider2 provider, String contactsIdString, Uri uri, 26007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 26017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = false; 26027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 26037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final String updatedSortOrder = (sortOrder == null) 26047a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana ? Data.RAW_CONTACT_ID 26057a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana : (Data.RAW_CONTACT_ID + "," + sortOrder); 26067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 26077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteDatabase db = provider.mOpenHelper.getReadableDatabase(); 26087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 2609226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setTables(Tables.CONTACT_ENTITIES); 26107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (contactsIdString != null) { 26115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.appendWhere(Data.RAW_CONTACT_ID + "=" + contactsIdString); 26127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 26136cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 26146cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 2615035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName)) { 26166cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 2617035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 26186cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 2619035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 2620035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 26217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 26227e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana null, null, updatedSortOrder); 26237e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.moveToFirst(); 26247e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 26257e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 26267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public void close() { 26277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 26287e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("closing when already closed"); 26297e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 26307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = true; 26317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.close(); 26327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 26337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 26347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public boolean hasNext() throws RemoteException { 26357e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 26367e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 26377e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 26387e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 26397e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return !mEntityCursor.isAfterLast(); 26407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 26417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 26427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public Entity next() throws RemoteException { 26437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 26447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 26457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 26467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (!hasNext()) { 26477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 26487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 26497e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 26507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 26517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 26527a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana final long rawContactId = c.getLong(COLUMN_RAW_CONTACT_ID); 26537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 26547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // we expect the cursor is already at the row we need to read from 26557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues contactValues = new ContentValues(); 26566cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 26576cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 26585ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov contactValues.put(RawContacts._ID, rawContactId); 26596cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.DIRTY, c.getLong(COLUMN_DIRTY)); 26606cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.VERSION, c.getLong(COLUMN_VERSION)); 26616cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 26627a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC1, c.getString(COLUMN_SYNC1)); 26637a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC2, c.getString(COLUMN_SYNC2)); 26647a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC3, c.getString(COLUMN_SYNC3)); 26657a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana contactValues.put(RawContacts.SYNC4, c.getString(COLUMN_SYNC4)); 26667e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana Entity contact = new Entity(contactValues); 26677e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 26687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // read data rows until the contact id changes 26697e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana do { 26707a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana if (rawContactId != c.getLong(COLUMN_RAW_CONTACT_ID)) { 26717e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 26727e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 26737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // add the data to to the contact 26747e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues dataValues = new ContentValues(); 26757a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data._ID, c.getString(COLUMN_DATA_ID)); 26767a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 26777a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.MIMETYPE, c.getString(COLUMN_MIMETYPE)); 26787a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.IS_PRIMARY, c.getString(COLUMN_IS_PRIMARY)); 26797a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 26809261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!c.isNull(COLUMN_GROUP_SOURCE_ID)) { 26819261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana dataValues.put(GroupMembership.GROUP_SOURCE_ID, 26829261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.getString(COLUMN_GROUP_SOURCE_ID)); 26839261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 26847a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana dataValues.put(Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 26857a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana for (int i = 0; i < DATA_KEYS.length; i++) { 26867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int columnIndex = i + COLUMN_DATA1; 26877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String key = DATA_KEYS[i]; 26887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (c.isNull(columnIndex)) { 26897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // don't put anything 26907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isLong(columnIndex)) { 26917e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getLong(columnIndex)); 26927e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isFloat(columnIndex)) { 26937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getFloat(columnIndex)); 26947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isString(columnIndex)) { 26957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getString(columnIndex)); 26967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isBlob(columnIndex)) { 26977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getBlob(columnIndex)); 26987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 26997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 27007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contact.addSubValue(Data.CONTENT_URI, dataValues); 27017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } while (mEntityCursor.moveToNext()); 27027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 27037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return contact; 27047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 27057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 27067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2707226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana /** 2708226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 2709226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 2710226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana */ 2711226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static class GroupsEntityIterator implements EntityIterator { 2712226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private final Cursor mEntityCursor; 2713226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private volatile boolean mIsClosed; 2714226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2715226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final String[] PROJECTION = new String[]{ 2716226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups._ID, 2717226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_NAME, 2718226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_TYPE, 2719226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.SOURCE_ID, 2720226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.DIRTY, 2721226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.VERSION, 2722226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.RES_PACKAGE, 2723226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE, 2724226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE_RES, 27257a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.GROUP_VISIBLE, 27267a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC1, 27277a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC2, 27287a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC3, 27297a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYNC4, 27307a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.SYSTEM_ID, 27317a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana Groups.NOTES}; 2732226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2733226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ID = 0; 2734226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_NAME = 1; 2735226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_TYPE = 2; 2736226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_SOURCE_ID = 3; 2737226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_DIRTY = 4; 2738226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_VERSION = 5; 2739226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_RES_PACKAGE = 6; 2740226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE = 7; 2741226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE_RES = 8; 2742226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_GROUP_VISIBLE = 9; 27437a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC1 = 10; 27447a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC2 = 11; 27457a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC3 = 12; 27467a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYNC4 = 13; 27477a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_SYSTEM_ID = 14; 27487a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana private static final int COLUMN_NOTES = 15; 2749226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2750226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public GroupsEntityIterator(ContactsProvider2 provider, String groupIdString, Uri uri, 2751226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 2752226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = false; 2753226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2754226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String updatedSortOrder = (sortOrder == null) 2755226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ? Groups._ID 2756226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana : (Groups._ID + "," + sortOrder); 2757226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2758226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteDatabase db = provider.mOpenHelper.getReadableDatabase(); 2759226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 2760226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setTables(Tables.GROUPS_JOIN_PACKAGES); 2761226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setProjectionMap(sGroupsProjectionMap); 2762226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (groupIdString != null) { 2763226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups._ID + "=" + groupIdString); 2764226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2765226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountName = uri.getQueryParameter(Groups.ACCOUNT_NAME); 2766226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountType = uri.getQueryParameter(Groups.ACCOUNT_TYPE); 2767226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!TextUtils.isEmpty(accountName)) { 2768226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups.ACCOUNT_NAME + "=" 2769226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 2770226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + Groups.ACCOUNT_TYPE + "=" 2771226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 2772226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2773226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 2774226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana null, null, updatedSortOrder); 2775226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToFirst(); 2776226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2777226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2778226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public void close() { 2779226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 2780226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("closing when already closed"); 2781226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2782226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = true; 2783226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.close(); 2784226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2785226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2786226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public boolean hasNext() throws RemoteException { 2787226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 2788226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 2789226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2790226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2791226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return !mEntityCursor.isAfterLast(); 2792226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2793226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2794226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public Entity next() throws RemoteException { 2795226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 2796226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 2797226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2798226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!hasNext()) { 2799226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 2800226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2801226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2802226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 2803226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2804226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final long groupId = c.getLong(COLUMN_ID); 2805226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2806226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana // we expect the cursor is already at the row we need to read from 2807226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ContentValues groupValues = new ContentValues(); 2808226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 2809226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 2810226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups._ID, groupId); 2811226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.DIRTY, c.getLong(COLUMN_DIRTY)); 2812226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.VERSION, c.getLong(COLUMN_VERSION)); 2813226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 2814226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 2815226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE, c.getString(COLUMN_TITLE)); 2816226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE_RES, c.getString(COLUMN_TITLE_RES)); 2817226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.GROUP_VISIBLE, c.getLong(COLUMN_GROUP_VISIBLE)); 28187a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC1, c.getString(COLUMN_SYNC1)); 28197a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC2, c.getString(COLUMN_SYNC2)); 28207a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC3, c.getString(COLUMN_SYNC3)); 28217a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYNC4, c.getString(COLUMN_SYNC4)); 28227a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.SYSTEM_ID, c.getString(COLUMN_SYSTEM_ID)); 28237a4550f2afb24b2112b6c937f416c6f46ece35f4Fred Quintana groupValues.put(Groups.NOTES, c.getString(COLUMN_NOTES)); 2824226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Entity group = new Entity(groupValues); 2825226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2826226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToNext(); 2827226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2828226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return group; 2829226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2830226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2831226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2832a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 28337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs, 28347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String sortOrder) { 28357e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int match = sUriMatcher.match(uri); 28367e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana switch (match) { 28375ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: 28385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: 28397e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String contactsIdString = null; 28405ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (match == RAW_CONTACTS_ID) { 28417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contactsIdString = uri.getPathSegments().get(1); 28427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 28437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 28447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return new ContactsEntityIterator(this, contactsIdString, 28457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana uri, selection, selectionArgs, sortOrder); 2846226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS: 2847226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS_ID: 2848226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String idString = null; 2849226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (match == GROUPS_ID) { 2850226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana idString = uri.getPathSegments().get(1); 2851226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2852226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2853226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return new GroupsEntityIterator(this, idString, 2854226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana uri, selection, selectionArgs, sortOrder); 28557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana default: 28567e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new UnsupportedOperationException("Unknown uri: " + uri); 28577e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 28587e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 28597e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 28604f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 28614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 2862a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 28634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 2864d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: return Contacts.CONTENT_TYPE; 2865d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: return Contacts.CONTENT_ITEM_TYPE; 28665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: return RawContacts.CONTENT_TYPE; 28675ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: return RawContacts.CONTENT_ITEM_TYPE; 2868508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 28696bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 2870508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 2871b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey return mOpenHelper.getDataMimeType(dataId); 287231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: return AggregationExceptions.CONTENT_TYPE; 287331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_EXCEPTION_ID: return AggregationExceptions.CONTENT_ITEM_TYPE; 2874d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: return Contacts.CONTENT_TYPE; 2875c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 2876c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 2877c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 2878c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 28794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 2880a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton throw new UnsupportedOperationException("Unknown uri: " + uri); 28814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 28827e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2883b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov @Override 28847e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 28857e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throws OperationApplicationException { 28867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 28877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 28887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana db.beginTransaction(); 28897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana try { 28907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentProviderResult[] results = super.applyBatch(operations); 28917e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana db.setTransactionSuccessful(); 28927e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return results; 28937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } finally { 28947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana db.endTransaction(); 28957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 28967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 2897c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 28985ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void setDisplayName(long rawContactId, String displayName) { 28993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (displayName != null) { 29003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mContactDisplayNameUpdate.bindString(1, displayName); 29013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 29023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mContactDisplayNameUpdate.bindNull(1); 29033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 29045ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mContactDisplayNameUpdate.bindLong(2, rawContactId); 29053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mContactDisplayNameUpdate.execute(); 29063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 29073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2908c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 2909c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 2910c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 2911c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 2912c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 2913c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 2914c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private void setIsPrimary(long dataId) { 2915c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 2916c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(2, dataId); 2917c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(3, dataId); 2918c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 2919c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 2920c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 2921c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 2922c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 2923c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 2924c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 2925c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 2926c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 2927c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private void setIsSuperPrimary(long dataId) { 2928c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 2929c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(2, dataId); 2930c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(3, dataId); 2931c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 2932619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2933619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Find the parent aggregate and package for this new primary 2934619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 2935619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2936619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey long aggId = -1; 2937619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey boolean isRestricted = false; 2938619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey String mimeType = null; 2939619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2940619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey Cursor cursor = null; 2941619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey try { 2942d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov cursor = db.query(DataRawContactsQuery.TABLE, DataRawContactsQuery.PROJECTION, 294367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey DataColumns.CONCRETE_ID + "=" + dataId, null, null, null, null); 2944619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (cursor.moveToFirst()) { 2945d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov aggId = cursor.getLong(DataRawContactsQuery.CONTACT_ID); 2946d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov isRestricted = (cursor.getInt(DataRawContactsQuery.IS_RESTRICTED) == 1); 2947d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov mimeType = cursor.getString(DataRawContactsQuery.MIMETYPE); 2948619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2949619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } finally { 2950619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (cursor != null) { 2951619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey cursor.close(); 2952619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2953619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2954619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2955619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Bypass aggregate update if no parent found, or if we don't keep track 2956619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // of super-primary for this mimetype. 2957d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov if (aggId == -1) { 2958d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return; 2959d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 2960619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2961619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey boolean isPhone = CommonDataKinds.Phone.CONTENT_ITEM_TYPE.equals(mimeType); 2962619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey boolean isEmail = CommonDataKinds.Email.CONTENT_ITEM_TYPE.equals(mimeType); 2963619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2964619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Record this value as the new primary for the parent aggregate 2965619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final ContentValues values = new ContentValues(); 2966619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (isPhone) { 2967d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(ContactsColumns.OPTIMAL_PRIMARY_PHONE_ID, dataId); 2968d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(ContactsColumns.OPTIMAL_PRIMARY_PHONE_IS_RESTRICTED, isRestricted); 2969619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } else if (isEmail) { 2970d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(ContactsColumns.OPTIMAL_PRIMARY_EMAIL_ID, dataId); 2971d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(ContactsColumns.OPTIMAL_PRIMARY_EMAIL_IS_RESTRICTED, isRestricted); 2972619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2973619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2974619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // If this data is unrestricted, then also set as fallback 2975619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (!isRestricted && isPhone) { 2976d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(ContactsColumns.FALLBACK_PRIMARY_PHONE_ID, dataId); 2977619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } else if (!isRestricted && isEmail) { 2978d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(ContactsColumns.FALLBACK_PRIMARY_EMAIL_ID, dataId); 2979619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2980619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2981d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // Push update into contacts table, if needed 2982619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (values.size() > 0) { 2983d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov db.update(Tables.CONTACTS, values, Contacts._ID + "=" + aggId, null); 2984619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2985c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 2986ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 2987d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private String buildContactLookupWhereClause(String filterParam) { 2988ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar StringBuilder filter = new StringBuilder(); 2989d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov filter.append(Tables.CONTACTS); 2990ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append("."); 2991d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov filter.append(Contacts._ID); 2992ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append(" IN (SELECT "); 2993d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov filter.append(RawContacts.CONTACT_ID); 2994ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append(" FROM "); 29955ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov filter.append(Tables.RAW_CONTACTS); 2996ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append(" WHERE "); 29976cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov filter.append(RawContacts._ID); 2998445ca81effbb0d61c7bc0033acf2d3dfd228fd4eDmitri Plotnikov filter.append(" IN "); 2999c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov appendRawContactsByFilterAsNestedQuery(filter, filterParam, null); 3000445ca81effbb0d61c7bc0033acf2d3dfd228fd4eDmitri Plotnikov filter.append(")"); 3001445ca81effbb0d61c7bc0033acf2d3dfd228fd4eDmitri Plotnikov return filter.toString(); 3002445ca81effbb0d61c7bc0033acf2d3dfd228fd4eDmitri Plotnikov } 3003445ca81effbb0d61c7bc0033acf2d3dfd228fd4eDmitri Plotnikov 30045ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 3005c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 3006c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam, null); 3007c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 3008c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3009c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 3010a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam, 3011c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit) { 3012c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append("(SELECT DISTINCT raw_contact_id FROM name_lookup WHERE normalized_name GLOB '"); 3013c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 3014c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append("*'"); 3015c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limit != null) { 3016c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(" LIMIT ").append(limit); 3017c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 3018c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(")"); 3019ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 3020ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 3021b67163a1088f09c59f324350662eb18772fac6b6Evan Millar private String[] appendGroupArg(String[] selectionArgs, String arg) { 3022b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 3023b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 3024b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 3025b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 3026b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 3027b67163a1088f09c59f324350662eb18772fac6b6Evan Millar System.arraycopy(selectionArgs, 0, newSelectionArgs, 0, selectionArgs.length); 3028b67163a1088f09c59f324350662eb18772fac6b6Evan Millar newSelectionArgs[newLength - 1] = arg; 3029b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 3030b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 3031b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 30324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 3033