ContactsProvider2.java revision a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0
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; 4467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.UriMatcher; 4567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.content.pm.PackageManager; 464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 47ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 48b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.database.sqlite.SQLiteCursor; 494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 504f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 51c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 53619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.os.Binder; 54b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 55508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 56de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract; 57b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 58de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds; 59d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.Contacts; 60de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.Data; 61ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.Groups; 621f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkeyimport android.provider.ContactsContract.Presence; 63d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts; 643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.BaseTypes; 65ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email; 66ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Im; 683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Nickname; 693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Organization; 70de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds.Phone; 714097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 7267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 73d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikovimport android.provider.ContactsContract.Contacts.AggregationSuggestions; 74a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 75a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 76c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikovimport android.util.Log; 774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 787e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 79b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 814f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 824f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 85035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintanapublic class ContactsProvider2 extends ContentProvider { 86b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey // TODO: clean up debug tag and rename this class 87b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey private static final String TAG = "ContactsProvider ~~~~"; 884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 89619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 90619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: check for restricted flag during insert(), update(), and delete() calls 91619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 95a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 97d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String STREQUENT_ORDER_BY = Contacts.STARRED + " DESC, " 98d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.TIMES_CONTACTED + " DESC, " 99d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.DISPLAY_NAME + " ASC"; 100d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 101d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "(SELECT COUNT(1) FROM " + Tables.CONTACTS + " WHERE " 102d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED + "=1) + 25"; 103d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov 104d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS = 1000; 105d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_ID = 1001; 106d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_DATA = 1002; 107d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final int CONTACTS_SUMMARY = 1003; 1082815f58f72f109790585931f601a63ddc02536a5Evan Millar private static final int CONTACTS_RAW_CONTACTS = 1004; 1092815f58f72f109790585931f601a63ddc02536a5Evan Millar private static final int CONTACTS_SUMMARY_ID = 1005; 1102815f58f72f109790585931f601a63ddc02536a5Evan Millar private static final int CONTACTS_SUMMARY_FILTER = 1006; 1112815f58f72f109790585931f601a63ddc02536a5Evan Millar private static final int CONTACTS_SUMMARY_STREQUENT = 1007; 1122815f58f72f109790585931f601a63ddc02536a5Evan Millar private static final int CONTACTS_SUMMARY_STREQUENT_FILTER = 1008; 1132815f58f72f109790585931f601a63ddc02536a5Evan Millar private static final int CONTACTS_SUMMARY_GROUP = 1009; 1144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1155ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS = 2002; 1165ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_ID = 2003; 1175ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static final int RAW_CONTACTS_DATA = 2004; 11828ab0f857caa92402878244d9c5ea2a59e070935Jeff Sharkey private static final int CONTACTS_FILTER_EMAIL = 2005; 1194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1206bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 1216bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 122ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 123ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES_FILTER = 3003; 124ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int POSTALS = 3004; 125a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1266bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 1276bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 128b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 129b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 130b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 1311f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private static final int PRESENCE = 7000; 1321f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private static final int PRESENCE_ID = 7001; 1331f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 13431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 13531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 136ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 137ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 138ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 139ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 14035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 14135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 142c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SUGGESTIONS = 12001; 143c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private static final int SEARCH_SHORTCUT = 12002; 144c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 14567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private interface ContactsQuery { 1465ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final String TABLE = Tables.RAW_CONTACTS; 1479261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 14867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 1496cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 1506cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 1516cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 152ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 153ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 15567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int ACCOUNT_NAME = 1; 15667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int ACCOUNT_TYPE = 2; 15767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 15867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 159d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataRawContactsQuery { 1605ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final String TABLE = Tables.DATA_JOIN_MIMETYPE_RAW_CONTACTS; 16167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 16267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 1636cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 1643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 165d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov RawContacts.CONTACT_ID, 1666cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.IS_RESTRICTED, 1673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.MIMETYPE, 168ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 169ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1705ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 17167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 172d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 17367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int IS_RESTRICTED = 3; 17467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int MIMETYPE = 4; 17567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 17667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 177d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private interface DataContactsQuery { 178d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final String TABLE = Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS; 17967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 18067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String[] PROJECTION = new String[] { 1816cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContactsColumns.CONCRETE_ID, 1823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 183d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.CONCRETE_ID, 1843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.CONCRETE_ID, 1853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Phone.NUMBER, 1863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Email.DATA, 187d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.OPTIMAL_PRIMARY_PHONE_ID, 188d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.FALLBACK_PRIMARY_PHONE_ID, 189d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.OPTIMAL_PRIMARY_EMAIL_ID, 190d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.FALLBACK_PRIMARY_EMAIL_ID, 191ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 192ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 193d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int RAW_CONTACT_ID = 0; 19467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA_ID = 1; 195d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public static final int CONTACT_ID = 2; 19667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int MIMETYPE_ID = 3; 19767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int PHONE_NUMBER = 4; 19867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int EMAIL_DATA = 5; 19967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int OPTIMAL_PHONE_ID = 6; 20067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int FALLBACK_PHONE_ID = 7; 20167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int OPTIMAL_EMAIL_ID = 8; 20267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int FALLBACK_EMAIL_ID = 9; 20380c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 204ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2051f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private interface DisplayNameQuery { 20767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final String[] COLUMNS = new String[] { 2103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 2123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA2, 2133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov StructuredName.DISPLAY_NAME, 2143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 0; 2173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 1; 2183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA2 = 2; 2193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DISPLAY_NAME = 3; 2203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private interface DataQuery { 22367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final String TABLE = Tables.DATA_JOIN_MIMETYPES; 2243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final String[] COLUMNS = new String[] { 2263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataColumns.CONCRETE_ID, 2273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov MimetypesColumns.MIMETYPE, 2285ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID, 2293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.IS_PRIMARY, 2303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA1, 2313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA2, 2323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA3, 2333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA4, 2343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA5, 2353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA6, 2363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA7, 2373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA8, 2383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA9, 2393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Data.DATA10, 24067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Data.DATA11, 24167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Data.DATA12, 24267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Data.DATA13, 24367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Data.DATA14, 24467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Data.DATA15, 2453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov }; 2463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int ID = 0; 2483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int MIMETYPE = 1; 2495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public static final int RAW_CONTACT_ID = 2; 2503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int IS_PRIMARY = 3; 2513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA1 = 4; 2523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA2 = 5; 2533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA3 = 6; 2543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA4 = 7; 2553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA5 = 8; 2563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA6 = 9; 2573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA7 = 10; 2583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA8 = 11; 2593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA9 = 12; 2603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public static final int DATA10 = 13; 26167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA11 = 14; 26267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA12 = 15; 26367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA13 = 16; 26467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA14 = 17; 26567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey public static final int DATA15 = 18; 2663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 2673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 26820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private interface DataIdQuery { 26920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String[] COLUMNS = { Data._ID }; 27020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 27120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int _ID = 0; 27220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 27320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 2743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov // Higher number represents higher priority in choosing what data to use for the display name 2753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DISPLAY_NAME_PRIORITY_EMAIL = 1; 2763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DISPLAY_NAME_PRIORITY_PHONE = 2; 2773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DISPLAY_NAME_PRIORITY_ORGANIZATION = 3; 2783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final int DISPLAY_NAME_PRIORITY_STRUCTURED_NAME = 4; 2793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private static final HashMap<String, Integer> sDisplayNamePriorities; 2813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov static { 2823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov sDisplayNamePriorities = new HashMap<String, Integer>(); 2833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov sDisplayNamePriorities.put(StructuredName.CONTENT_ITEM_TYPE, 2843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DISPLAY_NAME_PRIORITY_STRUCTURED_NAME); 2853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov sDisplayNamePriorities.put(Organization.CONTENT_ITEM_TYPE, 2863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DISPLAY_NAME_PRIORITY_ORGANIZATION); 2873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov sDisplayNamePriorities.put(Phone.CONTENT_ITEM_TYPE, 2883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DISPLAY_NAME_PRIORITY_PHONE); 2893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov sDisplayNamePriorities.put(Email.CONTENT_ITEM_TYPE, 2903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DISPLAY_NAME_PRIORITY_EMAIL); 2913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 29231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 2936bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** Contains just the contacts columns */ 2944f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 295d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Contains the contact columns along with primary phone */ 296d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sContactsSummaryProjectionMap; 297d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Contains the data, contacts, and contact columns, for joined tables. */ 2980c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar private static final HashMap<String, String> sDataRawContactsContactProjectionMap; 299d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Contains the data, contacts, group sourceid and contact columns, for joined tables. */ 3000c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar private static final HashMap<String, String> sDataRawContactsGroupsContactProjectionMap; 3012815f58f72f109790585931f601a63ddc02536a5Evan Millar /** Contains the contacts, and raw contact columns, for joined tables. */ 3022815f58f72f109790585931f601a63ddc02536a5Evan Millar private static final HashMap<String, String> sRawContactsContactsProjectionMap; 303d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Contains just the contacts columns */ 304d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final HashMap<String, String> sRawContactsProjectionMap; 305a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** Contains just the data columns */ 3069261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana private static final HashMap<String, String> sDataGroupsProjectionMap; 3079261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** Contains the data and contacts columns, for joined tables */ 3080c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar private static final HashMap<String, String> sDataRawContactsGroupsProjectionMap; 309a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** Contains the data and contacts columns, for joined tables */ 3100c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar private static final HashMap<String, String> sDataRawContactsProjectionMap; 311ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 312ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 313ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 314ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 315373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains the agg_exceptions columns */ 316b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 317373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov /** Contains Presence columns */ 318373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov private static final HashMap<String, String> sPresenceProjectionMap; 3197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 320c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Sql select statement that returns the contact id associated with a data record. */ 321d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String sNestedRawContactIdSelect; 322c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Sql select statement that returns the mimetype id associated with a data record. */ 323c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private static final String sNestedMimetypeSelect; 324d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Sql select statement that returns the contact id associated with a contact record. */ 325d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String sNestedContactIdSelect; 326d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Sql select statement that returns a list of contact ids associated with an contact record. */ 327c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private static final String sNestedContactIdListSelect; 328c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Sql where statement used to match all the data records that need to be updated when a new 329c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * "primary" is selected.*/ 330c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private static final String sSetPrimaryWhere; 331c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Sql where statement used to match all the data records that need to be updated when a new 332c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * "super primary" is selected.*/ 333c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private static final String sSetSuperPrimaryWhere; 334b67163a1088f09c59f324350662eb18772fac6b6Evan Millar /** Sql where statement for filtering on groups. */ 335d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private static final String sContactsInGroupSelect; 336c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 337c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 3383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for setting a data record to the super primary. */ 339c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 340d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov /** Precompiled sql statement for incrementing times contacted for an contact */ 341f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private SQLiteStatement mLastTimeContactedUpdate; 3423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** Precompiled sql statement for updating a contact display name */ 3433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private SQLiteStatement mContactDisplayNameUpdate; 344a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 3454f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 3464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 347a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 348d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 349d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 350d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 3512815f58f72f109790585931f601a63ddc02536a5Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/raw_contacts", CONTACTS_RAW_CONTACTS); 352d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts_summary", CONTACTS_SUMMARY); 353d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts_summary/#", CONTACTS_SUMMARY_ID); 354d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts_summary/filter/*", 355d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov CONTACTS_SUMMARY_FILTER); 356d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts_summary/strequent/", 357d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov CONTACTS_SUMMARY_STREQUENT); 358d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts_summary/strequent/filter/*", 359d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov CONTACTS_SUMMARY_STREQUENT_FILTER); 360d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts_summary/group/*", 361d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov CONTACTS_SUMMARY_GROUP); 362d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", 36331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 3645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS); 3655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID); 3665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#/data", RAW_CONTACTS_DATA); 3675ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/filter_email/*", 368b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov CONTACTS_FILTER_EMAIL); 369b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 3704f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 3714f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 372ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 373ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 374ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 3751f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 376ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 377ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 378ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 379ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 38035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 38135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 382a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 383b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 384b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 385b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 386b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 3874f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 388bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "presence", PRESENCE); 389bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "presence/#", PRESENCE_ID); 3901f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 391c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, 392c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 393c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 394c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SUGGESTIONS); 395c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/#", 396c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov SEARCH_SHORTCUT); 397c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 398fec4e13316f2731d84394e5fa2f93af3febdc20cEvan Millar HashMap<String, String> columns; 3994f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 400d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // Contacts projection map 4016bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov columns = new HashMap<String, String>(); 402d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts._ID, "contacts._id AS _id"); 403d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.DISPLAY_NAME, ContactsColumns.CONCRETE_DISPLAY_NAME + " AS " 404d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.DISPLAY_NAME); 405d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.LAST_TIME_CONTACTED, ContactsColumns.CONCRETE_LAST_TIME_CONTACTED 406d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " AS " + Contacts.LAST_TIME_CONTACTED); 407d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.TIMES_CONTACTED, ContactsColumns.CONCRETE_TIMES_CONTACTED + " AS " 408d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.TIMES_CONTACTED); 409d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.STARRED, ContactsColumns.CONCRETE_STARRED + " AS " 410d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.STARRED); 411d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.IN_VISIBLE_GROUP, Contacts.IN_VISIBLE_GROUP); 412d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.PHOTO_ID, Contacts.PHOTO_ID); 413d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.PRIMARY_PHONE_ID, Contacts.PRIMARY_PHONE_ID); 414d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.PRIMARY_EMAIL_ID, Contacts.PRIMARY_EMAIL_ID); 415d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.CUSTOM_RINGTONE, ContactsColumns.CONCRETE_CUSTOM_RINGTONE + " AS " 416d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.CUSTOM_RINGTONE); 417d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.SEND_TO_VOICEMAIL, ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL 418d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " AS " + Contacts.SEND_TO_VOICEMAIL); 419d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(ContactsColumns.FALLBACK_PRIMARY_PHONE_ID, 420d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.FALLBACK_PRIMARY_PHONE_ID); 421d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(ContactsColumns.FALLBACK_PRIMARY_EMAIL_ID, 422d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.FALLBACK_PRIMARY_EMAIL_ID); 423d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sContactsProjectionMap = columns; 4246bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 4251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey columns = new HashMap<String, String>(); 426d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.putAll(sContactsProjectionMap); 427c62855331805c2744a097ef6ea625652197bfb87Dmitri Plotnikov 428d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // Contacts primaries projection map. The overall presence status is 429c62855331805c2744a097ef6ea625652197bfb87Dmitri Plotnikov // the most-present value, as indicated by the largest value. 430d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.PRESENCE_STATUS, "MAX(" + Presence.PRESENCE_STATUS + ")"); 431d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.PRIMARY_PHONE_TYPE, CommonDataKinds.Phone.TYPE); 432d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.PRIMARY_PHONE_LABEL, CommonDataKinds.Phone.LABEL); 433d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Contacts.PRIMARY_PHONE_NUMBER, CommonDataKinds.Phone.NUMBER); 434d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sContactsSummaryProjectionMap = columns; 43500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 4366cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts projection map 4374f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton columns = new HashMap<String, String>(); 4385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov columns.put(RawContacts._ID, Tables.RAW_CONTACTS + "." + RawContacts._ID + " AS _id"); 439d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(RawContacts.CONTACT_ID, RawContacts.CONTACT_ID); 4406cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov columns.put(RawContacts.ACCOUNT_NAME, 4415ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov OpenHelper.RawContactsColumns.CONCRETE_ACCOUNT_NAME 4425ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " AS " + RawContacts.ACCOUNT_NAME); 4436cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov columns.put(RawContacts.ACCOUNT_TYPE, 4445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov OpenHelper.RawContactsColumns.CONCRETE_ACCOUNT_TYPE 4455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " AS " + RawContacts.ACCOUNT_TYPE); 4466cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov columns.put(RawContacts.SOURCE_ID, 4475ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov OpenHelper.RawContactsColumns.CONCRETE_SOURCE_ID 4485ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " AS " + RawContacts.SOURCE_ID); 4496cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov columns.put(RawContacts.VERSION, 4505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov OpenHelper.RawContactsColumns.CONCRETE_VERSION 4515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " AS " + RawContacts.VERSION); 4526cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov columns.put(RawContacts.DIRTY, 4535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov OpenHelper.RawContactsColumns.CONCRETE_DIRTY 4545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " AS " + RawContacts.DIRTY); 45533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov columns.put(RawContacts.DELETED, 4565ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov OpenHelper.RawContactsColumns.CONCRETE_DELETED 4575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " AS " + RawContacts.DELETED); 458d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sRawContactsProjectionMap = columns; 4594f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 4602815f58f72f109790585931f601a63ddc02536a5Evan Millar columns = new HashMap<String, String>(); 4612815f58f72f109790585931f601a63ddc02536a5Evan Millar columns.putAll(sContactsProjectionMap); 4622815f58f72f109790585931f601a63ddc02536a5Evan Millar columns.putAll(sRawContactsProjectionMap); 4632815f58f72f109790585931f601a63ddc02536a5Evan Millar sRawContactsContactsProjectionMap = columns; 4642815f58f72f109790585931f601a63ddc02536a5Evan Millar 4654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Data projection map 4664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton columns = new HashMap<String, String>(); 4675ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov columns.put(Data._ID, Tables.DATA + "." + Data._ID + " AS _id"); 4685ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov columns.put(Data.RAW_CONTACT_ID, Data.RAW_CONTACT_ID); 46967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Data.RES_PACKAGE, PackagesColumns.PACKAGE + " AS " + Data.RES_PACKAGE); 470508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey columns.put(Data.MIMETYPE, Data.MIMETYPE); 471c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar columns.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 472c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar columns.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 473f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana columns.put(Data.DATA_VERSION, Data.DATA_VERSION); 4747e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA1, "data.data1 as data1"); 4757e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA2, "data.data2 as data2"); 4767e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA3, "data.data3 as data3"); 4777e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA4, "data.data4 as data4"); 4787e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA5, "data.data5 as data5"); 4797e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA6, "data.data6 as data6"); 4807e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA7, "data.data7 as data7"); 4817e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA8, "data.data8 as data8"); 4827e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA9, "data.data9 as data9"); 4837e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA10, "data.data10 as data10"); 48467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Data.DATA11, "data.data11 as data11"); 48567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Data.DATA12, "data.data12 as data12"); 48667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Data.DATA13, "data.data13 as data13"); 48767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Data.DATA14, "data.data14 as data14"); 48867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Data.DATA15, "data.data15 as data15"); 48967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(GroupMembership.GROUP_SOURCE_ID, GroupsColumns.CONCRETE_SOURCE_ID + " AS " 49067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey + GroupMembership.GROUP_SOURCE_ID); 49120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 49220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // TODO: remove this projection 493d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Mappings used for backwards compatibility. 494d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar columns.put("number", Phone.NUMBER); 4959261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana sDataGroupsProjectionMap = columns; 496a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 4979261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // Data, groups and contacts projection map for joins. _id comes from the data table 498a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton columns = new HashMap<String, String>(); 499d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.putAll(sRawContactsProjectionMap); 5009261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.putAll(sDataGroupsProjectionMap); // _id will be replaced with the one from data 501d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Data.RAW_CONTACT_ID, DataColumns.CONCRETE_RAW_CONTACT_ID); 5020c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar sDataRawContactsGroupsProjectionMap = columns; 5039261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 5049261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // Data and contacts projection map for joins. _id comes from the data table 5059261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns = new HashMap<String, String>(); 5060c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar columns.putAll(sDataRawContactsGroupsProjectionMap); 5079261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.remove(GroupMembership.GROUP_SOURCE_ID); 5080c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar sDataRawContactsProjectionMap = columns; 5097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 510de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millar // Data and contacts projection map for joins. _id comes from the data table 511de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millar columns = new HashMap<String, String>(); 512d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.putAll(sContactsProjectionMap); 513d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.putAll(sRawContactsProjectionMap); // 5149261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.putAll(sDataGroupsProjectionMap); // _id will be replaced with the one from data 515d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Data.RAW_CONTACT_ID, DataColumns.CONCRETE_RAW_CONTACT_ID); 5160c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar sDataRawContactsGroupsContactProjectionMap = columns; 5179261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 5189261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // Data and contacts projection map for joins. _id comes from the data table 5199261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns = new HashMap<String, String>(); 5200c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar columns.putAll(sDataRawContactsGroupsContactProjectionMap); 5219261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.remove(GroupMembership.GROUP_SOURCE_ID); 5220c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar sDataRawContactsContactProjectionMap = columns; 523c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 524ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 525ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 526ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups._ID, "groups._id AS _id"); 527035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 528035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 5299261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.SOURCE_ID, Groups.SOURCE_ID); 5309261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.DIRTY, Groups.DIRTY); 5319261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana columns.put(Groups.VERSION, Groups.VERSION); 53267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.RES_PACKAGE, PackagesColumns.PACKAGE + " AS " + Groups.RES_PACKAGE); 533ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 53467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey columns.put(Groups.TITLE_RES, Groups.TITLE_RES); 535ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 536ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 537ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5386cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov // RawContacts and groups projection map 539ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 540ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 541ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 542d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + ContactsColumns.CONCRETE_ID 543d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ") FROM " + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 544ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 545ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 546ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 547ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 548d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + ContactsColumns.CONCRETE_ID + ") FROM " 549d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS + " WHERE " 550ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 551ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + " AND " + Clauses.HAS_PRIMARY_PHONE + ") AS " + Groups.SUMMARY_WITH_PHONES); 552ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 553ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 554ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 555b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 556b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 557b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 558b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 559d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov columns.put(AggregationExceptions.CONTACT_ID, 560d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov "raw_contacts1." + RawContacts.CONTACT_ID 561d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " AS " + AggregationExceptions.CONTACT_ID); 5625ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov columns.put(AggregationExceptions.RAW_CONTACT_ID, AggregationExceptionColumns.RAW_CONTACT_ID2); 563b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 564b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 565373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov 566373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns = new HashMap<String, String>(); 567373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence._ID, Presence._ID); 568373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.RAW_CONTACT_ID, Presence.RAW_CONTACT_ID); 569373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.DATA_ID, Presence.DATA_ID); 570373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.IM_ACCOUNT, Presence.IM_ACCOUNT); 571373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.IM_HANDLE, Presence.IM_HANDLE); 572373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.IM_PROTOCOL, Presence.IM_PROTOCOL); 573373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.PRESENCE_STATUS, Presence.PRESENCE_STATUS); 574373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov columns.put(Presence.PRESENCE_CUSTOM_STATUS, Presence.PRESENCE_CUSTOM_STATUS); 575373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov sPresenceProjectionMap = columns; 576373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov 577d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sNestedRawContactIdSelect = "SELECT " + Data.RAW_CONTACT_ID + " FROM " + Tables.DATA + " WHERE " 578c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + Data._ID + "=?"; 579c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar sNestedMimetypeSelect = "SELECT " + DataColumns.MIMETYPE_ID + " FROM " + Tables.DATA 580c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + " WHERE " + Data._ID + "=?"; 581d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sNestedContactIdSelect = "SELECT " + RawContacts.CONTACT_ID + " FROM " + Tables.RAW_CONTACTS 582d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " WHERE " + RawContacts._ID + "=(" + sNestedRawContactIdSelect + ")"; 5835ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov sNestedContactIdListSelect = "SELECT " + RawContacts._ID + " FROM " + Tables.RAW_CONTACTS 584d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " WHERE " + RawContacts.CONTACT_ID + "=(" + sNestedContactIdSelect + ")"; 585d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sSetPrimaryWhere = Data.RAW_CONTACT_ID + "=(" + sNestedRawContactIdSelect + ") AND " 586c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + DataColumns.MIMETYPE_ID + "=(" + sNestedMimetypeSelect + ")"; 5875ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov sSetSuperPrimaryWhere = Data.RAW_CONTACT_ID + " IN (" + sNestedContactIdListSelect + ") AND " 588c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + DataColumns.MIMETYPE_ID + "=(" + sNestedMimetypeSelect + ")"; 589d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sContactsInGroupSelect = ContactsColumns.CONCRETE_ID + " IN (SELECT " 590d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + RawContacts.CONTACT_ID + " FROM " + Tables.RAW_CONTACTS + " WHERE (" 5916cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContactsColumns.CONCRETE_ID + " IN (SELECT " + Tables.DATA + "." 5925ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + Data.RAW_CONTACT_ID + " FROM " + Tables.DATA_JOIN_MIMETYPES + " WHERE (" 593b67163a1088f09c59f324350662eb18772fac6b6Evan Millar + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE + "' AND " 594b67163a1088f09c59f324350662eb18772fac6b6Evan Millar + GroupMembership.GROUP_ROW_ID + "=(SELECT " + Tables.GROUPS + "." 595b67163a1088f09c59f324350662eb18772fac6b6Evan Millar + Groups._ID + " FROM " + Tables.GROUPS + " WHERE " + Groups.TITLE + "=?)))))"; 5964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 5974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 5983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 5993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Handles inserts and update for a specific Data type. 6003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 6013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private abstract class DataRowHandler { 6023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected final String mMimetype; 6043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public DataRowHandler(String mimetype) { 6063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mMimetype = mimetype; 6073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 6103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Inserts a row into the {@link Data} table. 6113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 6125ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 613e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov final long dataId = db.insert(Tables.DATA, null, values); 614e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 615e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov Integer primary = values.getAsInteger(Data.IS_PRIMARY); 616e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primary != null && primary != 0) { 617e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov setIsPrimary(dataId); 618e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 619e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 6205ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixContactDisplayName(db, rawContactId); 621e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return dataId; 6223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 6253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Validates data and updates a {@link Data} row using the cursor, which contains 6263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * the current data. 6273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 6283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor cursor) { 6293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov throw new UnsupportedOperationException(); 6303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public int delete(SQLiteDatabase db, Cursor c) { 6333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov long dataId = c.getLong(DataQuery.ID); 6345ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = c.getLong(DataQuery.RAW_CONTACT_ID); 6353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov boolean primary = c.getInt(DataQuery.IS_PRIMARY) != 0; 6363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov int count = db.delete(Tables.DATA, Data._ID + "=" + dataId, null); 6373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (count != 0 && primary) { 6385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixPrimary(db, rawContactId); 6395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixContactDisplayName(db, rawContactId); 6403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return count; 6423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void fixPrimary(SQLiteDatabase db, long rawContactId) { 6455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long newPrimaryId = findNewPrimaryDataId(db, rawContactId); 6463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (newPrimaryId != -1) { 6473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov ContactsProvider2.this.setIsPrimary(newPrimaryId); 6483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected long findNewPrimaryDataId(SQLiteDatabase db, long rawContactId) { 652e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long primaryId = -1; 653e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int primaryType = -1; 6545ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Cursor c = queryData(db, rawContactId); 6553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 656e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov while (c.moveToNext()) { 657e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov long dataId = c.getLong(DataQuery.ID); 658e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov int type = c.getInt(DataQuery.DATA2); 659e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (primaryType == -1 || getTypeRank(type) < getTypeRank(primaryType)) { 660e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryId = dataId; 661e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov primaryType = type; 662e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 6633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 6653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 6663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 667e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return primaryId; 668e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 669e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 670e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov /** 671e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * Returns the rank of a specific record type to be used in determining the primary 672e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov * row. Lower number represents higher priority. 673e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov */ 674e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 675e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return 0; 6763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected Cursor queryData(SQLiteDatabase db, long rawContactId) { 6793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov // TODO Lookup integer mimetype IDs' instead of joining for speed 6805ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return db.query(DataQuery.TABLE, DataQuery.COLUMNS, Data.RAW_CONTACT_ID + "=" 6815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + rawContactId + " AND " + MimetypesColumns.MIMETYPE + "='" + mMimetype + "'", 6823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov null, null, null, null); 6833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 6843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 6855ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov protected void fixContactDisplayName(SQLiteDatabase db, long rawContactId) { 686e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (!sDisplayNamePriorities.containsKey(mMimetype)) { 687e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return; 688e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 689e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 6903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String bestDisplayName = null; 69167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Cursor c = db.query(DisplayNameQuery.TABLE, DisplayNameQuery.COLUMNS, 6925ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov Data.RAW_CONTACT_ID + "=" + rawContactId, null, null, null, null); 6933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov try { 6943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov int maxPriority = -1; 6953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov while (c.moveToNext()) { 6963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String mimeType = c.getString(DisplayNameQuery.MIMETYPE); 6973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov boolean primary; 6983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String name; 6993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) { 7013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov name = c.getString(DisplayNameQuery.DISPLAY_NAME); 7023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov primary = true; 7033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 7043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov name = c.getString(DisplayNameQuery.DATA2); 7053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov primary = (c.getInt(DisplayNameQuery.IS_PRIMARY) != 0); 7063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7083cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (primary && name != null) { 7093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov Integer priority = sDisplayNamePriorities.get(mimeType); 7103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (priority != null && priority > maxPriority) { 7113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov maxPriority = priority; 7123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov bestDisplayName = name; 7133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } finally { 7183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov c.close(); 7193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7215ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov ContactsProvider2.this.setDisplayName(rawContactId, bestDisplayName); 7223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CustomDataRowHandler extends DataRowHandler { 7263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CustomDataRowHandler(String mimetype) { 7283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 7293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class StructuredNameRowHandler extends DataRowHandler { 7333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final NameSplitter mNameSplitter; 7353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public StructuredNameRowHandler(NameSplitter nameSplitter) { 7373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(StructuredName.CONTENT_ITEM_TYPE); 7383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mNameSplitter = nameSplitter; 7393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 7425ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 7433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov fixStructuredNameComponents(values); 7445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return super.insert(db, rawContactId, values); 7453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 7483cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor cursor) { 7493cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov // TODO Parse the full name if it has changed and replace pre-existing piece parts. 7503cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov /** 7533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * Parses the supplied display name, but only if the incoming values do not already contain 7543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * structured name parts. Also, if the display name is not provided, generate one by 7553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * concatenating first name and last name 7563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * 7573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * TODO see if the order of first and last names needs to be conditionally reversed for 7583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov * some locales, e.g. China. 7593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov */ 7603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private void fixStructuredNameComponents(ContentValues values) { 7613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String fullName = values.getAsString(StructuredName.DISPLAY_NAME); 7623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (!TextUtils.isEmpty(fullName) 7633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov && TextUtils.isEmpty(values.getAsString(StructuredName.PREFIX)) 7643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov && TextUtils.isEmpty(values.getAsString(StructuredName.GIVEN_NAME)) 7653cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov && TextUtils.isEmpty(values.getAsString(StructuredName.MIDDLE_NAME)) 7663cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov && TextUtils.isEmpty(values.getAsString(StructuredName.FAMILY_NAME)) 7673cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov && TextUtils.isEmpty(values.getAsString(StructuredName.SUFFIX))) { 7683cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 7693cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mNameSplitter.split(name, fullName); 7703cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7713cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.PREFIX, name.getPrefix()); 7723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.GIVEN_NAME, name.getGivenNames()); 7733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.MIDDLE_NAME, name.getMiddleName()); 7743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.FAMILY_NAME, name.getFamilyName()); 7753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.SUFFIX, name.getSuffix()); 7763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7773cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (TextUtils.isEmpty(fullName)) { 7793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String givenName = values.getAsString(StructuredName.GIVEN_NAME); 7803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String familyName = values.getAsString(StructuredName.FAMILY_NAME); 7813cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (TextUtils.isEmpty(givenName)) { 7823cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov fullName = familyName; 7833cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else if (TextUtils.isEmpty(familyName)) { 7843cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov fullName = givenName; 7853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 7863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov fullName = givenName + " " + familyName; 7873cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (!TextUtils.isEmpty(fullName)) { 7903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov values.put(StructuredName.DISPLAY_NAME, fullName); 7913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 7953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class CommonDataRowHandler extends DataRowHandler { 7973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 7983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mTypeColumn; 7993cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private final String mLabelColumn; 8003cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8013cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public CommonDataRowHandler(String mimetype, String typeColumn, String labelColumn) { 8023cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(mimetype); 8033cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mTypeColumn = typeColumn; 8043cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mLabelColumn = labelColumn; 8053cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8063cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 8085ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 8093cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov int type; 8103cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov String label; 8113cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (values.containsKey(mTypeColumn)) { 8123cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov type = values.getAsInteger(mTypeColumn); 8133cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 8143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov type = BaseTypes.TYPE_CUSTOM; 8153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (values.containsKey(mLabelColumn)) { 8173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov label = values.getAsString(mLabelColumn); 8183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 8193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov label = null; 8203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (type != BaseTypes.TYPE_CUSTOM && label != null) { 8233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov throw new RuntimeException(mLabelColumn + " value can only be specified with " 8243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov + mTypeColumn + "=" + BaseTypes.TYPE_CUSTOM + "(custom)"); 8253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (type == BaseTypes.TYPE_CUSTOM && label == null) { 8283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov throw new RuntimeException(mLabelColumn + " value must be specified when " 8293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov + mTypeColumn + "=" + BaseTypes.TYPE_CUSTOM + "(custom)"); 8303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8325ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return super.insert(db, rawContactId, values); 8333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8353cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 8363cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public void update(SQLiteDatabase db, ContentValues values, Cursor cursor) { 8373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov // TODO read the data and check the constraint 8383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class OrganizationDataRowHandler extends CommonDataRowHandler { 8423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public OrganizationDataRowHandler() { 8443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Organization.CONTENT_ITEM_TYPE, Organization.TYPE, Organization.LABEL); 8453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8463cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8473cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 8485ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 8495ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long id = super.insert(db, rawContactId, values); 8505ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixContactDisplayName(db, rawContactId); 8513cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return id; 8523cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8533cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8543cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 8553cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 8563cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 8573cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_WORK: return 0; 8583cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_CUSTOM: return 1; 8593cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Organization.TYPE_OTHER: return 2; 8603cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 8613cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8623cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8633cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8643cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 865e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public class EmailDataRowHandler extends CommonDataRowHandler { 866e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 867e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov public EmailDataRowHandler() { 868e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov super(Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL); 869e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 870e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 871e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 8725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 8735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long id = super.insert(db, rawContactId, values); 8745ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov fixContactDisplayName(db, rawContactId); 875e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov return id; 876e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 877e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 878e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov @Override 879e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov protected int getTypeRank(int type) { 880e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov switch (type) { 881e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_HOME: return 0; 882e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_WORK: return 1; 883e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_CUSTOM: return 2; 884e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov case Email.TYPE_OTHER: return 3; 885e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov default: return 1000; 886e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 887e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 888e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 889e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 8903cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public class PhoneDataRowHandler extends CommonDataRowHandler { 8913cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov public PhoneDataRowHandler() { 8933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov super(Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); 8943cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 8953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 8963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 8975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { 898e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov ContentValues phoneValues = new ContentValues(); 899e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String number = values.getAsString(Phone.NUMBER); 900e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov String normalizedNumber = null; 901e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 902e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov normalizedNumber = PhoneNumberUtils.getStrippedReversed(number); 903e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov values.put(PhoneColumns.NORMALIZED_NUMBER, normalizedNumber); 904e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 905e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov 9065ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long id = super.insert(db, rawContactId, values); 9073cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 908e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov if (number != null) { 9095ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); 910e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.DATA_ID, id); 911e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); 912e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov db.insert(Tables.PHONE_LOOKUP, null, phoneValues); 913e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov } 9143cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9153cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return id; 9163cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9173cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9183cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov @Override 9193cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov protected int getTypeRank(int type) { 9203cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov switch (type) { 9213cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_MOBILE: return 0; 9223cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_WORK: return 1; 9233cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_HOME: return 2; 9243cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_PAGER: return 3; 9253cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_CUSTOM: return 4; 9263cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_OTHER: return 5; 9273cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_WORK: return 6; 9283cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov case Phone.TYPE_FAX_HOME: return 7; 9293cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov default: return 1000; 9303cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9313cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9323cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 9333cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9343cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private HashMap<String, DataRowHandler> mDataRowHandlers; 93553056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov private final ContactAggregationScheduler mAggregationScheduler; 9364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private OpenHelper mOpenHelper; 93731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 938a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov private ContactAggregator mContactAggregator; 9394097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 940f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov private LegacyApiSupport mLegacyApiSupport; 941a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov private GlobalSearchSupport mGlobalSearchSupport; 942a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 94320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private ContentValues mValues = new ContentValues(); 94420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 945a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov public ContactsProvider2() { 94653056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov this(new ContactAggregationScheduler()); 947a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 948a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 949a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 950a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Constructor for testing. 951a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 95253056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov /* package */ ContactsProvider2(ContactAggregationScheduler scheduler) { 95353056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov mAggregationScheduler = scheduler; 954a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 9554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 9564f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 9574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 958b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey final Context context = getContext(); 95935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 96031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov mOpenHelper = getOpenHelper(context); 961a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mGlobalSearchSupport = new GlobalSearchSupport(this); 962a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov mLegacyApiSupport = new LegacyApiSupport(context, mOpenHelper, this, mGlobalSearchSupport); 96353056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov mContactAggregator = new ContactAggregator(context, mOpenHelper, mAggregationScheduler); 964a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 965d51a83ac4f8032b62d9a23b90a8f43d6b7eb2dbbDmitri Plotnikov final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 966c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement = db.compileStatement( 967c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar "UPDATE " + Tables.DATA + " SET " + Data.IS_PRIMARY 968c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + "=(_id=?) WHERE " + sSetPrimaryWhere); 969c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement = db.compileStatement( 970c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar "UPDATE " + Tables.DATA + " SET " + Data.IS_SUPER_PRIMARY 971c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + "=(_id=?) WHERE " + sSetSuperPrimaryWhere); 9725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mLastTimeContactedUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 9736cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContacts.TIMES_CONTACTED + "=" + RawContacts.TIMES_CONTACTED + "+1," 974d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + RawContacts.LAST_TIME_CONTACTED + "=? WHERE " + RawContacts.CONTACT_ID + "=?"); 975a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 9765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mContactDisplayNameUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 9776cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContactsColumns.DISPLAY_NAME + "=? WHERE " + RawContacts._ID + "=?"); 9783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 97928f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar mNameSplitter = new NameSplitter( 98028f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_prefixes), 98128f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_last_name_prefixes), 98228f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_suffixes), 98328f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_conjunctions)); 9844097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 9853cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers = new HashMap<String, DataRowHandler>(); 9863cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 987e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov mDataRowHandlers.put(Email.CONTENT_ITEM_TYPE, new EmailDataRowHandler()); 9883cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Im.CONTENT_ITEM_TYPE, 9893cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new CommonDataRowHandler(Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL)); 99067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 99167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, StructuredPostal.LABEL)); 9923cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Organization.CONTENT_ITEM_TYPE, new OrganizationDataRowHandler()); 9933cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(Phone.CONTENT_ITEM_TYPE, new PhoneDataRowHandler()); 99467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey mDataRowHandlers.put(Nickname.CONTENT_ITEM_TYPE, new CommonDataRowHandler( 99567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey Nickname.CONTENT_ITEM_TYPE, Nickname.TYPE, Nickname.LABEL)); 9963cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(StructuredName.CONTENT_ITEM_TYPE, 9973cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov new StructuredNameRowHandler(mNameSplitter)); 9983cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 9991f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return (db != null); 10004f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 10014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 100231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 100331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov protected OpenHelper getOpenHelper(final Context context) { 100431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov return OpenHelper.getInstance(context); 100531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 100631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1007a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 1008a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov protected void finalize() throws Throwable { 1009a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov if (mContactAggregator != null) { 1010a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mContactAggregator.quit(); 1011a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1012a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1013a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov super.finalize(); 1014a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1015a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1016a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 1017a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 1018a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 1019a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 1020a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mOpenHelper.wipeData(); 1021a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 1022a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1023a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1024a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Called when a change has been made. 1025a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 1026a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param uri the uri that the change was made to 1027a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 1028a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private void onChange(Uri uri) { 1029a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null); 1030a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1031a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 10324f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 10334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean isTemporary() { 10344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return false; 10354f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 10364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 10373cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov private DataRowHandler getDataRowHandler(final String mimeType) { 10383cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov DataRowHandler handler = mDataRowHandlers.get(mimeType); 10393cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (handler == null) { 10403cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov handler = new CustomDataRowHandler(mimeType); 10413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mDataRowHandlers.put(mimeType, handler); 10423cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10433cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return handler; 10443cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 10453cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 10464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 10474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Uri insert(Uri uri, ContentValues values) { 1048a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 1049a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 105035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1051a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 105235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 105335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana id = mOpenHelper.getSyncState().insert(mOpenHelper.getWritableDatabase(), values); 105435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 105535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1056d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 1057d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov insertContact(values); 10586bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 10596bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 10606bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 10615ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 1062f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana final Account account = readAccountFromQueryParams(uri); 1063d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov id = insertRawContact(values, account); 1064a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1065a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1066a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 10675ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 10685ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Data.RAW_CONTACT_ID, uri.getPathSegments().get(1)); 1069035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana id = insertData(values); 1070a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1071a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1072a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1073a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 1074035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana id = insertData(values); 1075a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1076a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1077a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1078ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 1079ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final Account account = readAccountFromQueryParams(uri); 1080ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey id = insertGroup(values, account); 1081ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1082ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1083ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 10841f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey case PRESENCE: { 10851f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey id = insertPresence(values); 10861f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 10871f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 10881f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1089a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 1090f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.insert(uri, values); 1091a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1092a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 10937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 10947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 10957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 10967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 10977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final Uri result = ContentUris.withAppendedId(uri, id); 1098a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton onChange(result); 1099a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return result; 1100a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1101a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1102a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1103035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * If account is non-null then store it in the values. If the account is already 1104035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * specified in the values then it must be consistent with the account, if it is non-null. 1105035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param values the ContentValues to read from and update 1106035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param account the explicitly provided Account 1107035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @return false if the accounts are inconsistent 11087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 1109035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private boolean resolveAccount(ContentValues values, Account account) { 1110035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana // If either is specified then both must be specified. 11116cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = values.getAsString(RawContacts.ACCOUNT_NAME); 11126cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 1113035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName) || !TextUtils.isEmpty(accountType)) { 1114035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final Account valuesAccount = new Account(accountName, accountType); 1115035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null && !valuesAccount.equals(account)) { 1116035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return false; 1117035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1118035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana account = valuesAccount; 1119035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1120035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null) { 11216cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov values.put(RawContacts.ACCOUNT_NAME, account.mName); 11226cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov values.put(RawContacts.ACCOUNT_TYPE, account.mType); 1123035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 1124035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return true; 11257e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 11267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 11277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 1128d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Inserts an item in the contacts table 11296bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 11306bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 11316bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 11326bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 1133d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertContact(ContentValues values) { 1134a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov throw new UnsupportedOperationException("Aggregates are created automatically"); 11356bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 11366bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 11376bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 1138a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 1139a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 1140a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 1141f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana * @param account the account this contact should be associated with. may be null. 1142a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 1143a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 1144d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private long insertRawContact(ContentValues values, Account account) { 11456bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /* 11466bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * The contact record is inserted in the contacts table, but it needs to 11476bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * be processed by the aggregator before it will be returned by the 11486bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * "aggregates" queries. 11496bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 1150a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 11516bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 1152a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov ContentValues overriddenValues = new ContentValues(values); 1153d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov overriddenValues.putNull(RawContacts.CONTACT_ID); 1154f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana if (!resolveAccount(overriddenValues, account)) { 11557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return -1; 11567e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 11577e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 1158c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return db.insert(Tables.RAW_CONTACTS, RawContacts.CONTACT_ID, overriddenValues); 1159a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1160a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1161a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 1162a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 1163a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 1164a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 1165a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 1166a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 1167035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private long insertData(ContentValues values) { 11686cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov int aggregationMode = RawContacts.AGGREGATION_MODE_DISABLED; 1169a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1170a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 1171a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 1172a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton db.beginTransaction(); 1173a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton try { 117420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 117520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 117620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 11775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID); 1178a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 117967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey // Replace package with internal mapping 118020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov final String packageName = mValues.getAsString(Data.RES_PACKAGE); 118167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 118220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 118367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 118420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 118567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 1186619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Replace mimetype with internal mapping 118720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov final String mimeType = mValues.getAsString(Data.MIMETYPE); 118820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.isEmpty(mimeType)) { 118920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov throw new RuntimeException(Data.MIMETYPE + " is required"); 119020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 119120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 119220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.put(DataColumns.MIMETYPE_ID, mOpenHelper.getMimeTypeId(mimeType)); 119320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 1194508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 11953cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (GroupMembership.CONTENT_ITEM_TYPE.equals(mimeType)) { 119620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean containsGroupSourceId = mValues.containsKey(GroupMembership.GROUP_SOURCE_ID); 119720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean containsGroupId = mValues.containsKey(GroupMembership.GROUP_ROW_ID); 11989261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (containsGroupSourceId && containsGroupId) { 11999261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException( 12009261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID " 12019261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "and GroupMembership.GROUP_ROW_ID"); 12029261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 12039261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 12049261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!containsGroupSourceId && !containsGroupId) { 12059261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException( 12069261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana "you must set exactly one of GroupMembership.GROUP_SOURCE_ID " 12079261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "and GroupMembership.GROUP_ROW_ID"); 12089261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 12099261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 12109261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (containsGroupSourceId) { 121120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov final String sourceId = mValues.getAsString(GroupMembership.GROUP_SOURCE_ID); 12125ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov final long groupId = getOrMakeGroup(db, rawContactId, sourceId); 121320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(GroupMembership.GROUP_SOURCE_ID); 121420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.put(GroupMembership.GROUP_ROW_ID, groupId); 12159261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 12164097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov } 12174097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 12185ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov id = getDataRowHandler(mimeType).insert(db, rawContactId, mValues); 1219a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 12205ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov aggregationMode = mContactAggregator.markContactForAggregation(rawContactId); 1221a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1222a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton db.setTransactionSuccessful(); 1223a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } finally { 1224a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton db.endTransaction(); 1225a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1226a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 1227f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov triggerAggregation(id, aggregationMode); 1228a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 12294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 12304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 12315ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void triggerAggregation(long rawContactId, int aggregationMode) { 1232f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov switch (aggregationMode) { 12336cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DEFAULT: 1234f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov mContactAggregator.schedule(); 1235f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 1236f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 12376cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_IMMEDITATE: 12385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mContactAggregator.aggregateContact(rawContactId); 1239f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 1240f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 12416cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov case RawContacts.AGGREGATION_MODE_DISABLED: 1242f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov // Do nothing 1243f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov break; 1244f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 1245f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 1246f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov 1247a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 12485ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Returns the group id of the group with sourceId and the same account as rawContactId. 12499261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * If the group doesn't already exist then it is first created, 12509261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param db SQLiteDatabase to use for this operation 12515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * @param rawContactId the contact this group is associated with 12529261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @param sourceId the sourceIf of the group to query or create 12539261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @return the group id of the existing or created group 12549261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalArgumentException if the contact is not associated with an account 12559261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana * @throws IllegalStateException if a group needs to be created but the creation failed 12569261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana */ 12575ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId) { 12589261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Account account = null; 12596cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov Cursor c = db.query(ContactsQuery.TABLE, ContactsQuery.PROJECTION, RawContacts._ID + "=" 12605ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + rawContactId, null, null, null, null); 12619261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 12629261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 126367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountName = c.getString(ContactsQuery.ACCOUNT_NAME); 126467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String accountType = c.getString(ContactsQuery.ACCOUNT_TYPE); 12659261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 12669261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana account = new Account(accountName, accountType); 12679261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 12689261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 12699261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 12709261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 12719261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 12729261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (account == null) { 12739261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalArgumentException("if the groupmembership only " 12749261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "has a sourceid the the contact must be associate with " 12759261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "an account"); 12769261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 12779261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 12789261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana // look up the group that contains this sourceId and has the same account name and type 12795ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov // as the contact refered to by rawContactId 12806cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov c = db.query(Tables.GROUPS, new String[]{RawContacts._ID}, 12819261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID, 12829261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana new String[]{sourceId, account.mName, account.mType}, null, null, null); 12839261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana try { 12849261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (c.moveToNext()) { 12859261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return c.getLong(0); 12869261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } else { 12879261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana ContentValues groupValues = new ContentValues(); 12889261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, account.mName); 12899261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, account.mType); 12909261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana groupValues.put(Groups.SOURCE_ID, sourceId); 12919261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana long groupId = db.insert(Tables.GROUPS, Groups.ACCOUNT_NAME, groupValues); 12929261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (groupId < 0) { 12939261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana throw new IllegalStateException("unable to create a new group with " 12949261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana + "this sourceid: " + groupValues); 12959261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 12969261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana return groupId; 12979261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 12989261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } finally { 12999261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.close(); 13009261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 13019261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 13029261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana 13039261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana /** 130420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov * Delete data row by row so that fixing of primaries etc work correctly. 130520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov */ 130620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private int deleteData(String selection, String[] selectionArgs) { 130720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 130820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 130920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov db.beginTransaction(); 131020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 131120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 131220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 131320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 131420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataIdQuery.COLUMNS, selection, selectionArgs, null); 131520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 131620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov while(c.moveToNext()) { 131720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov long dataId = c.getLong(DataIdQuery._ID); 131820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov count += deleteData(dataId); 131920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 132020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 132120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 132220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 132320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov db.setTransactionSuccessful(); 132420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 132520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov db.endTransaction(); 132620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 132720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 132820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 132920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 133020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 133120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov public int deleteData(long dataId, String[] allowedMimeTypes) { 133220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 133320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov Cursor c = db.query(DataQuery.TABLE, DataQuery.COLUMNS, 133420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov DataColumns.CONCRETE_ID + "=" + dataId, null, null, null, null); 133520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // TODO apply restrictions 133620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 133720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!c.moveToFirst()) { 133820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 133920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 134020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 134120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String mimeType = c.getString(DataQuery.MIMETYPE); 134220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov boolean valid = false; 134320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov for (int i = 0; i < allowedMimeTypes.length; i++) { 134420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (TextUtils.equals(mimeType, allowedMimeTypes[i])) { 134520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov valid = true; 134620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 134720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 134820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 134920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 135020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (!valid) { 135120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov throw new RuntimeException("Data type mismatch: expected " 135220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov + Lists.newArrayList(allowedMimeTypes)); 135320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 135420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 135520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return getDataRowHandler(mimeType).delete(db, c); 135620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 135720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 135820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 135920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 136020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 136120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov /** 1362d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Delete the given {@link Data} row, fixing up any {@link Contacts} 1363ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * primaries that reference it. 1364ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 1365ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private int deleteData(long dataId) { 1366ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 1367ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1368ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final long mimePhone = mOpenHelper.getMimeTypeId(Phone.CONTENT_ITEM_TYPE); 1369ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final long mimeEmail = mOpenHelper.getMimeTypeId(Email.CONTENT_ITEM_TYPE); 1370ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1371ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Check to see if the data about to be deleted was a super-primary on 1372ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // the parent aggregate, and set flags to fix-up once deleted. 1373ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long aggId = -1; 1374ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long mimeId = -1; 1375ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey String dataRaw = null; 1376ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey boolean fixOptimal = false; 1377ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey boolean fixFallback = false; 1378ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1379ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Cursor cursor = null; 1380ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey try { 1381d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov cursor = db.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 138267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey DataColumns.CONCRETE_ID + "=" + dataId, null, null, null, null); 1383ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (cursor.moveToFirst()) { 1384d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov aggId = cursor.getLong(DataContactsQuery.CONTACT_ID); 1385d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov mimeId = cursor.getLong(DataContactsQuery.MIMETYPE_ID); 1386ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (mimeId == mimePhone) { 1387d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov dataRaw = cursor.getString(DataContactsQuery.PHONE_NUMBER); 1388d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov fixOptimal = (cursor.getLong(DataContactsQuery.OPTIMAL_PHONE_ID) == dataId); 1389d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov fixFallback = (cursor.getLong(DataContactsQuery.FALLBACK_PHONE_ID) == dataId); 1390ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } else if (mimeId == mimeEmail) { 1391d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov dataRaw = cursor.getString(DataContactsQuery.EMAIL_DATA); 1392d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov fixOptimal = (cursor.getLong(DataContactsQuery.OPTIMAL_EMAIL_ID) == dataId); 1393d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov fixFallback = (cursor.getLong(DataContactsQuery.FALLBACK_EMAIL_ID) == dataId); 1394ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1395ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1396ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } finally { 1397ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (cursor != null) { 1398ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor.close(); 1399ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor = null; 1400ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1401ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1402ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1403ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Delete the requested data item. 1404ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey int dataDeleted = db.delete(Tables.DATA, Data._ID + "=" + dataId, null); 1405ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1406ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Fix-up any super-primary values that are now invalid. 1407ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (fixOptimal || fixFallback) { 1408ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 1409ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final StringBuilder scoreClause = new StringBuilder(); 1410ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1411ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final String SCORE = "score"; 1412ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1413ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Build scoring clause that will first pick data items under the 1414ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // same aggregate that have identical values, otherwise fall back to 1415ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // normal primary scoring from the member contacts. 1416ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.append("(CASE WHEN "); 1417ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (mimeId == mimePhone) { 1418ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.append(Phone.NUMBER); 1419ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } else if (mimeId == mimeEmail) { 1420ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.append(Email.DATA); 1421ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1422ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.append("="); 1423ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey DatabaseUtils.appendEscapedSQLString(scoreClause, dataRaw); 1424ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.append(" THEN 2 ELSE " + Data.IS_PRIMARY + " END) AS " + SCORE); 1425ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1426ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final String[] PROJ_PRIMARY = new String[] { 1427ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey DataColumns.CONCRETE_ID, 14286cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.IS_RESTRICTED, 1429ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.toString(), 1430ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 1431ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1432ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final int COL_DATA_ID = 0; 1433ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final int COL_IS_RESTRICTED = 1; 143467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final int COL_SCORE = 2; 1435ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1436d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov cursor = db.query(Tables.DATA_JOIN_MIMETYPES_RAW_CONTACTS_CONTACTS, PROJ_PRIMARY, 1437d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov ContactsColumns.CONCRETE_ID + "=" + aggId + " AND " + DataColumns.MIMETYPE_ID 1438ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + "=" + mimeId, null, null, null, SCORE); 1439ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1440ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (fixOptimal) { 1441ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey String colId = null; 144267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey String colIsRestricted = null; 1443ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (mimeId == mimePhone) { 1444d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov colId = ContactsColumns.OPTIMAL_PRIMARY_PHONE_ID; 1445d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov colIsRestricted = ContactsColumns.OPTIMAL_PRIMARY_PHONE_IS_RESTRICTED; 1446ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } else if (mimeId == mimeEmail) { 1447d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov colId = ContactsColumns.OPTIMAL_PRIMARY_EMAIL_ID; 1448d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov colIsRestricted = ContactsColumns.OPTIMAL_PRIMARY_EMAIL_IS_RESTRICTED; 1449ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1450ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1451ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Start by replacing with null, since fixOptimal told us that 1452ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // the previous aggregate values are bad. 1453ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.putNull(colId); 145467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey values.putNull(colIsRestricted); 1455ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1456ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // When finding a new optimal primary, we only care about the 1457ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // highest scoring value, regardless of source. 1458ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (cursor.moveToFirst()) { 1459ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final long newOptimal = cursor.getLong(COL_DATA_ID); 146067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final long newIsRestricted = cursor.getLong(COL_IS_RESTRICTED); 1461ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1462ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (newOptimal != 0) { 1463ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(colId, newOptimal); 1464ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 146567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (newIsRestricted != 0) { 146667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey values.put(colIsRestricted, newIsRestricted); 1467ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1468ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1469ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1470ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1471ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (fixFallback) { 1472ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey String colId = null; 1473ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (mimeId == mimePhone) { 1474d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov colId = ContactsColumns.FALLBACK_PRIMARY_PHONE_ID; 1475ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } else if (mimeId == mimeEmail) { 1476d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov colId = ContactsColumns.FALLBACK_PRIMARY_EMAIL_ID; 1477ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1478ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1479ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Start by replacing with null, since fixFallback told us that 1480ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // the previous aggregate values are bad. 1481ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.putNull(colId); 1482ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1483ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // The best fallback value is the highest scoring data item that 1484ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // hasn't been restricted. 1485ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor.moveToPosition(-1); 1486ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey while (cursor.moveToNext()) { 1487ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final boolean isRestricted = (cursor.getInt(COL_IS_RESTRICTED) == 1); 1488ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!isRestricted) { 1489ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(colId, cursor.getLong(COL_DATA_ID)); 1490ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1491ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1492ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1493ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1494ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1495d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // Push through any contact updates we have 1496ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (values.size() > 0) { 1497d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov db.update(Tables.CONTACTS, values, ContactsColumns.CONCRETE_ID + "=" + aggId, 1498ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey null); 1499ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1500ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1501ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1502ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return dataDeleted; 1503ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1504ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1505ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 1506ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 1507ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 1508ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private long insertGroup(ContentValues values, Account account) { 1509ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 1510ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1511ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContentValues overriddenValues = new ContentValues(values); 1512ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!resolveAccount(overriddenValues, account)) { 1513ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return -1; 1514ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1515ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1516ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 151767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String packageName = overriddenValues.getAsString(Groups.RES_PACKAGE); 151867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (packageName != null) { 151967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey overriddenValues.put(GroupsColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 152067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 152167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey overriddenValues.remove(Groups.RES_PACKAGE); 1522ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1523ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return db.insert(Tables.GROUPS, Groups.TITLE, overriddenValues); 1524ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1525ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1526ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 15271f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey * Inserts a presence update. 15281f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 152970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public long insertPresence(ContentValues values) { 15301f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 15311f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey final String handle = values.getAsString(Presence.IM_HANDLE); 15321f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey final String protocol = values.getAsString(Presence.IM_PROTOCOL); 15331f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (TextUtils.isEmpty(handle) || TextUtils.isEmpty(protocol)) { 15341f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey throw new IllegalArgumentException("IM_PROTOCOL and IM_HANDLE are required"); 15351f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 15361f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 15371f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // TODO: generalize to allow other providers to match against email 1538a01e50cb1a5dd21293f8a8fe43f3fe0bf6349164Jeff Sharkey boolean matchEmail = Im.PROTOCOL_GOOGLE_TALK == Integer.parseInt(protocol); 15391f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 154070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov StringBuilder selection = new StringBuilder(); 15411f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String[] selectionArgs; 15421f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (matchEmail) { 154370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov selection.append("(" + Clauses.WHERE_IM_MATCHES + ") OR (" 154470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov + Clauses.WHERE_EMAIL_MATCHES + ")"); 15451f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey selectionArgs = new String[] { protocol, handle, handle }; 15461f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 154770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov selection.append(Clauses.WHERE_IM_MATCHES); 15481f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey selectionArgs = new String[] { protocol, handle }; 15491f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 15501f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 155170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (values.containsKey(Presence.DATA_ID)) { 155270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov selection.append(" AND " + DataColumns.CONCRETE_ID + "=") 155370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov .append(values.getAsLong(Presence.DATA_ID)); 155470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 155570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 15565ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (values.containsKey(Presence.RAW_CONTACT_ID)) { 1557d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov selection.append(" AND " + DataColumns.CONCRETE_RAW_CONTACT_ID + "=") 15585ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov .append(values.getAsLong(Presence.RAW_CONTACT_ID)); 155970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 156070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 156170b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov selection.append(" AND ").append(getContactsRestrictionExceptions()); 156270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 15631f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey long dataId = -1; 15645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = -1; 156570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 15661f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 15671f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 156870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov cursor = db.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 156970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov selection.toString(), selectionArgs, null, null, null); 15701f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 157167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey dataId = cursor.getLong(DataContactsQuery.DATA_ID); 15725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 15731f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 15741f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 15751f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 15761f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 15771f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 157831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 157931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 158031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 15811f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 15821f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 15831f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey values.put(Presence.DATA_ID, dataId); 15845ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov values.put(Presence.RAW_CONTACT_ID, rawContactId); 15851f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 15861f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // Insert the presence update 15871f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey long presenceId = db.replace(Tables.PRESENCE, null, values); 15881f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return presenceId; 15891f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 15901f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 15914f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 15924f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public int delete(Uri uri, String selection, String[] selectionArgs) { 1593508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 1594508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 1595508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 159635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 159735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana return mOpenHelper.getSyncState().delete(db, selection, selectionArgs); 159835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1599d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 1600d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = ContentUris.parseId(uri); 16016bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 1602d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // Remove references to the contact first 16036bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov ContentValues values = new ContentValues(); 1604d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.putNull(RawContacts.CONTACT_ID); 16055ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov db.update(Tables.RAW_CONTACTS, values, 1606d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov RawContacts.CONTACT_ID + "=" + contactId, null); 16076bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 1608d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov return db.delete(Tables.CONTACTS, BaseColumns._ID + "=" + contactId, null); 16096bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 16106bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 16115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 161233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov return deleteRawContact(uri); 1613508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 1614508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 161520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 161620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return deleteData(selection, selectionArgs); 161720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 161820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1619508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: { 1620508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 1621ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return deleteData(dataId); 1622ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1623ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1624ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 1625ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 1626ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final long groupMembershipMimetypeId = mOpenHelper 1627ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 1628ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey int groupsDeleted = db.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 1629ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey int dataDeleted = db.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 1630ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 1631ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + groupId, null); 1632ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey mOpenHelper.updateAllVisible(); 1633ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return groupsDeleted + dataDeleted; 1634508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 1635508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 16361f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey case PRESENCE: { 16371f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return db.delete(Tables.PRESENCE, null, null); 16381f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 16391f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1640508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey default: 16413cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov return mLegacyApiSupport.delete(uri, selection, selectionArgs); 1642508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 16434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 16444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 164533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov private int deleteRawContact(Uri uri) { 164633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov boolean permanentDeletion = false; 164733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov String permanent = uri.getQueryParameter(RawContacts.DELETE_PERMANENTLY); 164833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov if (permanent != null && !"false".equals(permanent.toLowerCase())) { 164933b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov permanentDeletion = true; 165033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 165133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 16525ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 16535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return deleteRawContact(rawContactId, permanentDeletion); 165433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 165533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 16565ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public int deleteRawContact(long rawContactId, boolean permanently) { 165733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 165833b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 1659c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // TODO delete aggregation exceptions 1660c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov mOpenHelper.removeContactIfSingleton(rawContactId); 166133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov if (permanently) { 1662373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov db.delete(Tables.PRESENCE, Presence.RAW_CONTACT_ID + "=" + rawContactId, null); 16635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return db.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null); 166433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } else { 166533b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov mValues.clear(); 166633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov mValues.put(RawContacts.DELETED, true); 1667c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED); 1668c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov mValues.putNull(RawContacts.CONTACT_ID); 16695ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return updateRawContact(rawContactId, mValues, null, null); 167033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 167133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 167233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 1673f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana private static Account readAccountFromQueryParams(Uri uri) { 16746cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String name = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 16756cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String type = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 1676f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana if (TextUtils.isEmpty(name) || TextUtils.isEmpty(type)) { 1677f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana return null; 1678f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana } 1679f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana return new Account(name, type); 1680f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana } 1681f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana 1682ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 16834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 16844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 168500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 168635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 168700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 168800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 168900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 169035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 169135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana return mOpenHelper.getSyncState().update(db, values, selection, selectionArgs); 169235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1693d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // TODO(emillar): We will want to disallow editing the contacts table at some point. 1694d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 1695d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov count = db.update(Tables.CONTACTS, values, selection, selectionArgs); 169600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 169700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 169800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 1699d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 1700d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov count = updateContactData(db, ContentUris.parseId(uri), values); 1701c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 1702c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 1703c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 170420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA: { 170520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov count = updateData(values, selection, selectionArgs); 170620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov break; 170720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 1708c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 170920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov case DATA_ID: { 171020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov count = updateData(ContentUris.parseId(uri), values); 171100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 171200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 17137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17145ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 17155ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov count = db.update(Tables.RAW_CONTACTS, values, selection, selectionArgs); 17167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 17177e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17187e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17195ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 172033b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 172133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov count = updateRawContact(rawContactId, values, selection, selectionArgs); 17227e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 17237e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17247e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 1725ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 1726ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey count = db.update(Tables.GROUPS, values, selection, selectionArgs); 1727ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey mOpenHelper.updateAllVisible(); 1728ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1729ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1730ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1731ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 1732ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 1733ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey String selectionWithId = (Groups._ID + "=" + groupId + " ") 1734ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + (selection == null ? "" : " AND " + selection); 1735ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey count = db.update(Tables.GROUPS, values, selectionWithId, selectionArgs); 1736ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1737d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // If changing visibility, then update contacts 1738ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (values.containsKey(Groups.GROUP_VISIBLE)) { 1739ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey mOpenHelper.updateAllVisible(); 1740ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1741ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1742ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1743ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1744ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1745127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 1746127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov count = updateAggregationException(db, values); 1747b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 1748b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 1749b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 17507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana default: 1751f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.update(uri, values, selection, selectionArgs); 175200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 175300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 175400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar if (count > 0) { 175500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar getContext().getContentResolver().notifyChange(uri, null); 175600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 175700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 17584f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 17594f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 17605ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private int updateRawContact(long rawContactId, ContentValues values, String selection, 176133b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov String[] selectionArgs) { 176233b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 17635ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov String selectionWithId = (RawContacts._ID + " = " + rawContactId + " ") 176433b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov + (selection == null ? "" : " AND " + selection); 17655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return db.update(Tables.RAW_CONTACTS, values, selectionWithId, selectionArgs); 176633b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov } 176733b41fdb8d7c3c654cb070799c9d6e2b4ab16078Dmitri Plotnikov 176820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private int updateData(ContentValues values, String selection, 176920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String[] selectionArgs) { 177020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 177120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov int count = 0; 177220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov db.beginTransaction(); 177320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 177420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 177520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Note that the query will return data according to the access restrictions, 177620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // so we don't need to worry about deleting data we don't have permission to read. 177720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov Cursor c = query(Data.CONTENT_URI, DataIdQuery.COLUMNS, selection, selectionArgs, null); 177820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov try { 177920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov while(c.moveToNext()) { 178020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov long dataId = c.getLong(DataIdQuery._ID); 178120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov count += updateData(dataId, values); 178220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 178320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 178420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov c.close(); 178520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 178620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov db.setTransactionSuccessful(); 178720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } finally { 178820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov db.endTransaction(); 178920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 179020a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 179120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return count; 179220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 179320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 179420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov private int updateData(long dataId, ContentValues values) { 179520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 179620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 179720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.clear(); 179820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.putAll(values); 179920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data._ID); 18005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mValues.remove(Data.RAW_CONTACT_ID); 180120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.MIMETYPE); 180220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 180320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov String packageName = values.getAsString(Data.RES_PACKAGE); 180420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (packageName != null) { 180520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.remove(Data.RES_PACKAGE); 180620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov mValues.put(DataColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 180720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 180820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 180970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); 181070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); 181120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 181220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Remove primary or super primary values being set to 0. This is disallowed by the 181320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // content provider. 181470b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 181520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsSuperPrimary = false; 181670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 181720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 181870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { 181920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov containsIsPrimary = false; 182070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 182120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 182220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 182320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (containsIsSuperPrimary) { 182420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov setIsSuperPrimary(dataId); 182520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov setIsPrimary(dataId); 182620a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 182720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Now that we've taken care of setting these, remove them from "values". 182870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_SUPER_PRIMARY); 182920a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov if (containsIsPrimary) { 183070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 183120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 183220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } else if (containsIsPrimary) { 183320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov setIsPrimary(dataId); 183420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 183520a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov // Now that we've taken care of setting this, remove it from "values". 183670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov mValues.remove(Data.IS_PRIMARY); 183720a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 183820a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 183970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (mValues.size() > 0) { 184070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return db.update(Tables.DATA, mValues, Data._ID + " = " + dataId, null); 184120a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 184220a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov return 0; 184320a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov } 184420a94c86ede7380c8dd8df2f6a72b3c00ac1bed8Dmitri Plotnikov 1845d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private int updateContactData(SQLiteDatabase db, long contactId, ContentValues values) { 1846d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1847d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // First update all constituent contacts 1848f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov ContentValues optionValues = new ContentValues(5); 18496cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov OpenHelper.copyStringValue(optionValues, RawContacts.CUSTOM_RINGTONE, 1850d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.CUSTOM_RINGTONE); 18516cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov OpenHelper.copyLongValue(optionValues, RawContacts.SEND_TO_VOICEMAIL, 1852d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.SEND_TO_VOICEMAIL); 18536cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov OpenHelper.copyLongValue(optionValues, RawContacts.LAST_TIME_CONTACTED, 1854d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.LAST_TIME_CONTACTED); 18556cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov OpenHelper.copyLongValue(optionValues, RawContacts.TIMES_CONTACTED, 1856d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.TIMES_CONTACTED); 18576cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov OpenHelper.copyLongValue(optionValues, RawContacts.STARRED, 1858d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values, Contacts.STARRED); 1859d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1860d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 1861d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov if (optionValues.size() == 0) { 1862d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 1863d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 1864d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 18655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov db.update(Tables.RAW_CONTACTS, optionValues, 1866d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov RawContacts.CONTACT_ID + "=" + contactId, null); 1867d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov return db.update(Tables.CONTACTS, values, Contacts._ID + "=" + contactId, null); 1868f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 1869d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1870d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov public void updateContactTime(long contactId, long lastTimeContacted) { 1871f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov mLastTimeContactedUpdate.bindLong(1, lastTimeContacted); 1872d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov mLastTimeContactedUpdate.bindLong(2, contactId); 1873f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov mLastTimeContactedUpdate.execute(); 1874d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 1875d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 18765ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private static class RawContactPair { 18775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov final long rawContactId1; 18785ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov final long rawContactId2; 1879127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 1880127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov /** 18815ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov * Constructor that ensures that this.rawContactId1 < this.rawContactId2 1882127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov */ 18835ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public RawContactPair(long rawContactId1, long rawContactId2) { 18845ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (rawContactId1 < rawContactId2) { 18855ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov this.rawContactId1 = rawContactId1; 18865ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov this.rawContactId2 = rawContactId2; 1887127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } else { 18885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov this.rawContactId2 = rawContactId1; 18895ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov this.rawContactId1 = rawContactId2; 1890127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 1891127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 1892127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 189380c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 1894127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 1895127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 1896d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = values.getAsInteger(AggregationExceptions.CONTACT_ID); 18975ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = values.getAsInteger(AggregationExceptions.RAW_CONTACT_ID); 189880c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 1899d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // First, we build a list of contactID-contactID pairs for the given contact and contact. 19005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov ArrayList<RawContactPair> pairs = new ArrayList<RawContactPair>(); 1901d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Cursor c = db.query(ContactsQuery.TABLE, ContactsQuery.PROJECTION, RawContacts.CONTACT_ID 1902d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + "=" + contactId, null, null, null, null); 1903127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov try { 1904127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov while (c.moveToNext()) { 19055ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long aggregatedContactId = c.getLong(ContactsQuery.RAW_CONTACT_ID); 19065ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (aggregatedContactId != rawContactId) { 19075ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov pairs.add(new RawContactPair(aggregatedContactId, rawContactId)); 1908e2e0ba75ce239f0f5481cdef9082daebf8fc2d35Dmitri Plotnikov } 1909b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 1910b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } finally { 1911b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov c.close(); 1912b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 1913127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 1914127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // Now we iterate through all contact pairs to see if we need to insert/delete/update 1915127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // the corresponding exception 1916127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 1917127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 19185ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov for (RawContactPair pair : pairs) { 1919127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov final String whereClause = 19205ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov AggregationExceptionColumns.RAW_CONTACT_ID1 + "=" + pair.rawContactId1 + " AND " 19215ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + AggregationExceptionColumns.RAW_CONTACT_ID2 + "=" + pair.rawContactId2; 1922127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 1923127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, whereClause, null); 1924127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } else { 19255ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov exceptionValues.put(AggregationExceptionColumns.RAW_CONTACT_ID1, pair.rawContactId1); 19265ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov exceptionValues.put(AggregationExceptionColumns.RAW_CONTACT_ID2, pair.rawContactId2); 1927127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 1928127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov exceptionValues); 1929127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 1930127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 1931127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 19325ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov int aggregationMode = mContactAggregator.markContactForAggregation(rawContactId); 19336cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov if (aggregationMode != RawContacts.AGGREGATION_MODE_DISABLED) { 19345ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mContactAggregator.aggregateContact(db, rawContactId); 1935f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC 1936f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov || exceptionType == AggregationExceptions.TYPE_KEEP_OUT) { 1937d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov mContactAggregator.updateAggregateData(contactId); 1938f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov } 19397a39bf269294a8130ddd463460b9b36cf4ff74a8Dmitri Plotnikov } 1940127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 1941127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 1942127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 1943127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 1944b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 1945b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 1946619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 1947619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Test if a {@link String} value appears in the given list. 1948619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 1949619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private boolean isContained(String[] array, String value) { 1950bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar if (array != null) { 1951bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar for (String test : array) { 1952bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar if (value.equals(test)) { 1953bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar return true; 1954bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar } 1955619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1956619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1957619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey return false; 1958619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1959619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1960619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 1961619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Test if a {@link String} value appears in the given list, and add to the 1962619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * array if the value doesn't already appear. 1963619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 1964619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private String[] assertContained(String[] array, String value) { 1965bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar if (array == null) { 1966bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar array = new String[] {value}; 1967bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar } else if (!isContained(array, value)) { 1968619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey String[] newArray = new String[array.length + 1]; 1969619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey System.arraycopy(array, 0, newArray, 0, array.length); 1970619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey newArray[array.length] = value; 1971619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey array = newArray; 1972619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1973619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey return array; 1974619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1975619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 19764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 19774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 19784f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 19794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 198035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1981d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 19821f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 1983c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit = getLimit(uri); 1984c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 1985d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov String contactIdColName = Tables.CONTACTS + "." + Contacts._ID; 19864f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1987619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 1988619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 1989a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 19904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 199135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 199235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana return mOpenHelper.getSyncState().query(db, projection, selection, selectionArgs, 199335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 199435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1995d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: { 1996d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.CONTACTS); 1997619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyAggregateRestrictionExceptions(qb); 1998d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov applyAggregatePrimaryRestrictionExceptions(sContactsProjectionMap); 1999d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 2000619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 2001619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2002619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2003d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: { 2004619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey long aggId = ContentUris.parseId(uri); 2005d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.CONTACTS); 2006d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(ContactsColumns.CONCRETE_ID + "=" + aggId + " AND "); 2007619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyAggregateRestrictionExceptions(qb); 2008d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov applyAggregatePrimaryRestrictionExceptions(sContactsProjectionMap); 2009d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sContactsProjectionMap); 20106bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 20116bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 20126bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 2013d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_SUMMARY: { 2014619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: join into social status tables 2015d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.CONTACTS_JOIN_PRESENCE_PRIMARY_PHONE); 2016619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyAggregateRestrictionExceptions(qb); 2017d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov applyAggregatePrimaryRestrictionExceptions(sContactsSummaryProjectionMap); 2018d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projection = assertContained(projection, Contacts.PRIMARY_PHONE_ID); 2019d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sContactsSummaryProjectionMap); 2020d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov groupBy = contactIdColName; 20211f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 20221f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 20231f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2024d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_SUMMARY_ID: { 2025619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: join into social status tables 20261f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey long aggId = ContentUris.parseId(uri); 2027d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.CONTACTS_JOIN_PRESENCE_PRIMARY_PHONE); 2028d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(ContactsColumns.CONCRETE_ID + "=" + aggId + " AND "); 2029619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyAggregateRestrictionExceptions(qb); 2030d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov applyAggregatePrimaryRestrictionExceptions(sContactsSummaryProjectionMap); 2031d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projection = assertContained(projection, Contacts.PRIMARY_PHONE_ID); 2032d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sContactsSummaryProjectionMap); 2033d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov groupBy = contactIdColName; 20341f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 20351f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 20361f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2037d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_SUMMARY_FILTER: { 2038619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: filter query based on callingUid 2039d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.CONTACTS_JOIN_PRESENCE_PRIMARY_PHONE); 2040d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sContactsSummaryProjectionMap); 2041ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 2042d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(buildContactLookupWhereClause(uri.getLastPathSegment())); 2043ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2044d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov groupBy = contactIdColName; 2045ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 2046ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2047ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 2048d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_SUMMARY_STREQUENT_FILTER: 2049d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_SUMMARY_STREQUENT: { 2050d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the first query for starred 2051d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.CONTACTS_JOIN_PRESENCE_PRIMARY_PHONE); 2052d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sContactsSummaryProjectionMap); 2053d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov if (match == CONTACTS_SUMMARY_STREQUENT_FILTER 2054d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 2055d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(buildContactLookupWhereClause(uri.getLastPathSegment())); 2056d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 2057d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov final String starredQuery = qb.buildQuery(projection, Contacts.STARRED + "=1", 2058d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov null, contactIdColName, null, null, 2059d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar null /* limit */); 2060d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 2061d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 2062d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 2063d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.CONTACTS_JOIN_PRESENCE_PRIMARY_PHONE); 2064d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sContactsSummaryProjectionMap); 2065d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov if (match == CONTACTS_SUMMARY_STREQUENT_FILTER 2066d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 2067d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(buildContactLookupWhereClause(uri.getLastPathSegment())); 2068d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 2069d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String frequentQuery = qb.buildQuery(projection, 2070d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Contacts.TIMES_CONTACTED + " > 0 AND (" + Contacts.STARRED 2071d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + " = 0 OR " + Contacts.STARRED + " IS NULL)", 2072d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov null, contactIdColName, null, null, null); 2073d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 2074d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 2075d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 2076d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 2077d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar Cursor c = db.rawQueryWithFactory(null, query, null, 2078d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov Tables.CONTACTS_JOIN_PRESENCE_PRIMARY_PHONE); 2079d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 2080d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar if ((c != null) && !isTemporary()) { 2081d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 2082d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 2083d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 2084d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 2085d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 2086d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 2087d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_SUMMARY_GROUP: { 2088d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.CONTACTS_JOIN_PRESENCE_PRIMARY_PHONE); 2089b67163a1088f09c59f324350662eb18772fac6b6Evan Millar applyAggregateRestrictionExceptions(qb); 2090d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov applyAggregatePrimaryRestrictionExceptions(sContactsSummaryProjectionMap); 2091d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projection = assertContained(projection, Contacts.PRIMARY_PHONE_ID); 2092d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sContactsSummaryProjectionMap); 2093b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 2094d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(" AND " + sContactsInGroupSelect); 2095b67163a1088f09c59f324350662eb18772fac6b6Evan Millar selectionArgs = appendGroupArg(selectionArgs, uri.getLastPathSegment()); 2096b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 2097d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov groupBy = contactIdColName; 2098b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 2099b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 2100b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 2101d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_DATA: { 2102619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey long aggId = Long.parseLong(uri.getPathSegments().get(1)); 2103d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS_GROUPS); 21040c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar qb.setProjectionMap(sDataRawContactsGroupsContactProjectionMap); 2105d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(RawContacts.CONTACT_ID + "=" + aggId + " AND "); 2106619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyDataRestrictionExceptions(qb); 21076bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 21086bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 210900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 21102815f58f72f109790585931f601a63ddc02536a5Evan Millar case CONTACTS_RAW_CONTACTS: { 21112815f58f72f109790585931f601a63ddc02536a5Evan Millar long contactId = Long.parseLong(uri.getPathSegments().get(1)); 21122815f58f72f109790585931f601a63ddc02536a5Evan Millar qb.setTables(Tables.RAW_CONTACTS_JOIN_CONTACTS); 21132815f58f72f109790585931f601a63ddc02536a5Evan Millar qb.setProjectionMap(sRawContactsContactsProjectionMap); 21142815f58f72f109790585931f601a63ddc02536a5Evan Millar qb.appendWhere(RawContacts.CONTACT_ID + "=" + contactId + " AND "); 21152815f58f72f109790585931f601a63ddc02536a5Evan Millar applyDataRestrictionExceptions(qb); 21162815f58f72f109790585931f601a63ddc02536a5Evan Millar break; 21172815f58f72f109790585931f601a63ddc02536a5Evan Millar } 21182815f58f72f109790585931f601a63ddc02536a5Evan Millar 2119ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 2120d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS); 21210c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar qb.setProjectionMap(sDataRawContactsContactProjectionMap); 2122ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.appendWhere(Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 2123ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 2124d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(" AND " + buildContactLookupWhereClause( 2125ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar uri.getLastPathSegment())); 2126ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2127ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 2128ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2129ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2130ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES: { 2131d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS); 21320c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar qb.setProjectionMap(sDataRawContactsContactProjectionMap); 2133ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.appendWhere(Data.MIMETYPE + " = \"" + Phone.CONTENT_ITEM_TYPE + "\""); 2134ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 2135ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2136ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 2137ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 2138d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS); 21390c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar qb.setProjectionMap(sDataRawContactsContactProjectionMap); 214067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey qb.appendWhere(Data.MIMETYPE + " = \"" + StructuredPostal.CONTENT_ITEM_TYPE + "\""); 2141ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 2142ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2143ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 21445ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: { 21455ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.setTables(Tables.RAW_CONTACTS); 2146d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sRawContactsProjectionMap); 2147619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyContactsRestrictionExceptions(qb); 21484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 21494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 21504f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 21515ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: { 21525ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = ContentUris.parseId(uri); 21535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.setTables(Tables.RAW_CONTACTS); 2154d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setProjectionMap(sRawContactsProjectionMap); 21555ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.appendWhere(RawContactsColumns.CONCRETE_ID + "=" + rawContactId + " AND "); 2156619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyContactsRestrictionExceptions(qb); 21574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 21584f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 21594f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 21605ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_DATA: { 21615ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 21625ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.setTables(Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_GROUPS); 21630c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar qb.setProjectionMap(sDataRawContactsGroupsProjectionMap); 21645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.appendWhere(Data.RAW_CONTACT_ID + "=" + rawContactId + " AND "); 2165619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyDataRestrictionExceptions(qb); 2166a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2167a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2168a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 216928ab0f857caa92402878244d9c5ea2a59e070935Jeff Sharkey case CONTACTS_FILTER_EMAIL: { 2170619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: filter query based on callingUid 2171d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_CONTACTS); 21720c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar qb.setProjectionMap(sDataRawContactsProjectionMap); 21735d0f923eb4c5351ebf323cc6f19c82acff98693eJeff Sharkey qb.appendWhere(Data.MIMETYPE + "='" + CommonDataKinds.Email.CONTENT_ITEM_TYPE + "'"); 2174e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey qb.appendWhere(" AND " + CommonDataKinds.Email.DATA + "="); 2175e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey qb.appendWhereEscapeString(uri.getPathSegments().get(2)); 2176e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 2177e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 2178e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 2179e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 21806cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 21816cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 2182343c56b5679c58bf1835a0e219fff57beae6ecefFred Quintana if (!TextUtils.isEmpty(accountName)) { 2183226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(RawContactsColumns.CONCRETE_ACCOUNT_NAME + "=" 2184035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 2185226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + RawContactsColumns.CONCRETE_ACCOUNT_TYPE + "=" 2186035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountType) + " AND "); 2187343c56b5679c58bf1835a0e219fff57beae6ecefFred Quintana } 21885ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.setTables(Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_GROUPS); 21899261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana qb.setProjectionMap(sDataGroupsProjectionMap); 2190619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyDataRestrictionExceptions(qb); 2191e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 2192e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 2193e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 21944f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 21955ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.setTables(Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_GROUPS); 21969261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana qb.setProjectionMap(sDataGroupsProjectionMap); 2197ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.appendWhere(DataColumns.CONCRETE_ID + "=" + ContentUris.parseId(uri) + " AND "); 2198619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyDataRestrictionExceptions(qb); 21994f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 22004f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 22014f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2202a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 2203619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: filter query based on callingUid 2204a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 2205a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 2206a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 22075ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov sortOrder = Data.RAW_CONTACT_ID; 2208a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2209a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2210a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final String number = uri.getLastPathSegment(); 2211bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov OpenHelper.buildPhoneLookupQuery(qb, number); 22120c83a3c4b6a9c8a0dfa0b3aa2af91b74d8e3304fEvan Millar qb.setProjectionMap(sDataRawContactsProjectionMap); 2213a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 2214a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 2215a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 2216ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 2217ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.GROUPS_JOIN_PACKAGES); 2218ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 2219ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2220ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2221ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2222ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 2223ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 2224ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.GROUPS_JOIN_PACKAGES); 2225ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 2226ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.appendWhere(GroupsColumns.CONCRETE_ID + "=" + groupId); 2227ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2228ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2229ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2230ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 2231d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.setTables(Tables.GROUPS_JOIN_PACKAGES_DATA_RAW_CONTACTS_CONTACTS); 2232ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 2233ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey groupBy = GroupsColumns.CONCRETE_ID; 2234ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 2235ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 2236ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 2237b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 22385ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS_JOIN_RAW_CONTACTS); 2239b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 2240b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 2241b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 2242b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 224331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 2244d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov long contactId = Long.parseLong(uri.getPathSegments().get(1)); 2245c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2246c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // TODO drop MAX_SUGGESTIONS in favor of LIMIT 224731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final String maxSuggestionsParam = 224831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov uri.getQueryParameter(AggregationSuggestions.MAX_SUGGESTIONS); 224931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 225031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 225131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (maxSuggestionsParam != null) { 225231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = Integer.parseInt(maxSuggestionsParam); 225331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 225431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 225531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 225631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 2257d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(contactId, projection, 2258d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov sContactsProjectionMap, maxSuggestions); 225931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 226031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 22615ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case PRESENCE: { 2262373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setTables(Tables.PRESENCE); 2263373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setProjectionMap(sPresenceProjectionMap); 22645ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 22655ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 22665ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 22675ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case PRESENCE_ID: { 2268373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setTables(Tables.PRESENCE); 2269373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.setProjectionMap(sPresenceProjectionMap); 2270373f7d2adc36680c31ff33e9ee12be865af6b5fbDmitri Plotnikov qb.appendWhere(Presence._ID + "=" + ContentUris.parseId(uri)); 22715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov break; 22725ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov } 22735ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov 2274c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: { 2275a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 2276c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 2277c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2278c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: { 2279c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // TODO 2280c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov break; 2281c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 2282c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 22834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 2284f4e1358f1c8f5fe5e9e7689e36e04c57c2385169Dmitri Plotnikov return mLegacyApiSupport.query(uri, projection, selection, selectionArgs, 2285c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sortOrder, limit); 22864f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 22874f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 22884f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Perform the query and set the notification uri 22891f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey final Cursor c = qb.query(db, projection, selection, selectionArgs, 2290bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar groupBy, null, sortOrder, limit); 22914f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 22924f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 22934f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 22944f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 22954f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 22964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 22977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 2298c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * Gets the value of the "limit" URI query parameter. 2299c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * 2300c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * @return A string containing a non-negative integer, or <code>null</code> if 2301c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov * the parameter is not set, or is set to an invalid value. 2302c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov */ 2303c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov private String getLimit(Uri url) { 2304c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limitParam = url.getQueryParameter("limit"); 2305c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limitParam == null) { 2306c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 2307c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 2308c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov // make sure that the limit is a non-negative integer 2309c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov try { 2310c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov int l = Integer.parseInt(limitParam); 2311c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (l < 0) { 2312c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 2313c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 2314c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 2315c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return String.valueOf(l); 2316c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } catch (NumberFormatException ex) { 2317c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov Log.w(TAG, "Invalid limit parameter: " + limitParam); 2318c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return null; 2319c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 2320c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 2321c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2322c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov /** 23236cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov * List of package names with access to {@link RawContacts#IS_RESTRICTED} data. 232467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey */ 232567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final String[] sAllowedPackages = new String[] { 232667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey "com.android.contacts", 232767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey "com.facebook", 232867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey }; 232967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 233067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey /** 233167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey * Check if {@link Binder#getCallingUid()} should be allowed access to 23326cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov * {@link RawContacts#IS_RESTRICTED} data. 233367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey */ 233467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private boolean hasRestrictedAccess() { 233567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final PackageManager pm = getContext().getPackageManager(); 233667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey final String[] callerPackages = pm.getPackagesForUid(Binder.getCallingUid()); 233767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 233867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey // Has restricted access if caller matches any packages 233967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey for (String callerPackage : callerPackages) { 234067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey for (String allowedPackage : sAllowedPackages) { 234167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (allowedPackage.equals(callerPackage)) { 234267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey return true; 234367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 234467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 234567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 234667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey return false; 234767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 234867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 234967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey /** 2350d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * Restrict selection of {@link Contacts} to only public ones, or those 235167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey * the caller has been granted an exception to. 2352619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 2353619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private void applyAggregateRestrictionExceptions(SQLiteQueryBuilder qb) { 235467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (hasRestrictedAccess()) { 235567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey qb.appendWhere("1"); 235667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 2357d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov qb.appendWhere(ContactsColumns.SINGLE_IS_RESTRICTED + "=0"); 2358619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2359619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2360619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2361619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 2362619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Find any exceptions that have been granted to the calling process, and 2363d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * add projections to correctly select {@link Contacts#PRIMARY_PHONE_ID} 2364d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov * and {@link Contacts#PRIMARY_EMAIL_ID}. 2365619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 2366619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private void applyAggregatePrimaryRestrictionExceptions(HashMap<String, String> projection) { 236767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey String projectionPhone; 236867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey String projectionEmail; 236967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 237067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (hasRestrictedAccess()) { 237167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey // With restricted access, always give optimal values 2372d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projectionPhone = ContactsColumns.OPTIMAL_PRIMARY_PHONE_ID + " AS " 2373d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.PRIMARY_PHONE_ID; 2374d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projectionEmail = ContactsColumns.OPTIMAL_PRIMARY_EMAIL_ID + " AS " 2375d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.PRIMARY_EMAIL_ID; 237667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 237767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey // With general access, always give fallback values 2378d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projectionPhone = ContactsColumns.FALLBACK_PRIMARY_PHONE_ID + " AS " 2379d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.PRIMARY_PHONE_ID; 2380d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projectionEmail = ContactsColumns.FALLBACK_PRIMARY_EMAIL_ID + " AS " 2381d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov + Contacts.PRIMARY_EMAIL_ID; 238267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } 238367dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey 2384d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projection.remove(Contacts.PRIMARY_PHONE_ID); 2385d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projection.put(Contacts.PRIMARY_PHONE_ID, projectionPhone); 2386619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2387d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projection.remove(Contacts.PRIMARY_EMAIL_ID); 2388d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov projection.put(Contacts.PRIMARY_EMAIL_ID, projectionEmail); 2389619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2390619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2391619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 2392619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Find any exceptions that have been granted to the 2393619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * {@link Binder#getCallingUid()}, and add a limiting clause to the given 2394619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * {@link SQLiteQueryBuilder} to hide restricted data. 2395619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 2396619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private void applyContactsRestrictionExceptions(SQLiteQueryBuilder qb) { 239770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov qb.appendWhere(getContactsRestrictionExceptions()); 239870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 239970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 2400a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov String getContactsRestrictionExceptions() { 240167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey if (hasRestrictedAccess()) { 240270b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 240370b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } else { 24046cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov return RawContacts.IS_RESTRICTED + "=0"; 240570b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 240670b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov } 240770b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov 240870b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov public String getContactsRestrictionExceptionAsNestedQuery(String contactIdColumn) { 240970b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov if (hasRestrictedAccess()) { 241070b5ee6864cb3368d24a9e876fb93008997b12dfDmitri Plotnikov return "1"; 241167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey } else { 24125ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov return "(SELECT " + RawContacts.IS_RESTRICTED + " FROM " + Tables.RAW_CONTACTS 24135ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov + " WHERE " + RawContactsColumns.CONCRETE_ID + "=" + contactIdColumn + ")=0"; 2414619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2415619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2416619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2417619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 2418619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Find any exceptions that have been granted to the 2419619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * {@link Binder#getCallingUid()}, and add a limiting clause to the given 2420619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * {@link SQLiteQueryBuilder} to hide restricted data. 2421619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 2422e80e514a6175ad2ee03ea6eff6201e0e47d5a710Dmitri Plotnikov void applyDataRestrictionExceptions(SQLiteQueryBuilder qb) { 2423619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyContactsRestrictionExceptions(qb); 2424619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2425619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2426619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 24277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 24287e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 24297e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 24307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static class ContactsEntityIterator implements EntityIterator { 24317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private final Cursor mEntityCursor; 24327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private volatile boolean mIsClosed; 24337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 24347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] DATA_KEYS = new String[]{ 24357e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data1", 24367e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data2", 24377e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data3", 24387e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data4", 24397e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data5", 24407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data6", 24417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data7", 24427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data8", 24437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data9", 244467dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey "data10", 244567dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey "data11", 244667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey "data12", 244767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey "data13", 244867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey "data14", 244967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey "data15"}; 24507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 24517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] PROJECTION = new String[]{ 24526cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_NAME, 24536cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.ACCOUNT_TYPE, 24546cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.SOURCE_ID, 24556cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.VERSION, 24566cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.DIRTY, 24576cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data._ID, 24586cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.RES_PACKAGE, 24596cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.MIMETYPE, 24606cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.DATA1, 24616cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.DATA2, 24626cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.DATA3, 24636cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.DATA4, 24646cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.DATA5, 24656cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.DATA6, 24666cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.DATA7, 24676cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.DATA8, 24686cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.DATA9, 24696cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.DATA10, 24706cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.DATA11, 24716cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.DATA12, 24726cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.DATA13, 24736cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.DATA14, 24746cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.DATA15, 24755ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov RawContacts.Data.RAW_CONTACT_ID, 24766cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.IS_PRIMARY, 24776cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov RawContacts.Data.DATA_VERSION, 24789261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana GroupMembership.GROUP_SOURCE_ID}; 2479035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana 2480035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_NAME = 0; 2481035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_TYPE = 1; 2482035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_SOURCE_ID = 2; 2483035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_VERSION = 3; 2484035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DIRTY = 4; 2485035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DATA_ID = 5; 248667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_RES_PACKAGE = 6; 248767dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_MIMETYPE = 7; 248867dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_DATA1 = 8; 248967dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_CONTACT_ID = 23; 249067dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_IS_PRIMARY = 24; 249167dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_DATA_VERSION = 25; 249267dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey private static final int COLUMN_GROUP_SOURCE_ID = 26; 24937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 24947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public ContactsEntityIterator(ContactsProvider2 provider, String contactsIdString, Uri uri, 24957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 24967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = false; 24977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 24987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final String updatedSortOrder = (sortOrder == null) 24995ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov ? RawContacts.Data.RAW_CONTACT_ID 25005ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov : (RawContacts.Data.RAW_CONTACT_ID + "," + sortOrder); 25017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteDatabase db = provider.mOpenHelper.getReadableDatabase(); 25037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 2504226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setTables(Tables.CONTACT_ENTITIES); 25057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (contactsIdString != null) { 25065ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov qb.appendWhere(Data.RAW_CONTACT_ID + "=" + contactsIdString); 25077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25086cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 25096cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE); 2510035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName)) { 25116cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov qb.appendWhere(RawContacts.ACCOUNT_NAME + "=" 2512035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 25136cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov + RawContacts.ACCOUNT_TYPE + "=" 2514035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 2515035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 25167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 25177e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana null, null, updatedSortOrder); 25187e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.moveToFirst(); 25197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public void close() { 25227e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 25237e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("closing when already closed"); 25247e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25257e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = true; 25267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.close(); 25277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25287e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25297e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public boolean hasNext() throws RemoteException { 25307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 25317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 25327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return !mEntityCursor.isAfterLast(); 25357e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25367e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25377e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public Entity next() throws RemoteException { 25387e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 25397e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 25407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (!hasNext()) { 25427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 25437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 25467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25475ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov final long rawContactId = c.getLong(COLUMN_CONTACT_ID); 25487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25497e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // we expect the cursor is already at the row we need to read from 25507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues contactValues = new ContentValues(); 25516cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 25526cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 25535ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov contactValues.put(RawContacts._ID, rawContactId); 25546cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.DIRTY, c.getLong(COLUMN_DIRTY)); 25556cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.VERSION, c.getLong(COLUMN_VERSION)); 25566cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov contactValues.put(RawContacts.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 25577e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana Entity contact = new Entity(contactValues); 25587e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25597e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // read data rows until the contact id changes 25607e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana do { 25615ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (rawContactId != c.getLong(COLUMN_CONTACT_ID)) { 25627e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 25637e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // add the data to to the contact 25657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues dataValues = new ContentValues(); 25666cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov dataValues.put(RawContacts.Data._ID, c.getString(COLUMN_DATA_ID)); 25676cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov dataValues.put(RawContacts.Data.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 25686cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov dataValues.put(RawContacts.Data.MIMETYPE, c.getString(COLUMN_MIMETYPE)); 25696cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov dataValues.put(RawContacts.Data.IS_PRIMARY, c.getString(COLUMN_IS_PRIMARY)); 25706cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov dataValues.put(RawContacts.Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 25719261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana if (!c.isNull(COLUMN_GROUP_SOURCE_ID)) { 25729261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana dataValues.put(GroupMembership.GROUP_SOURCE_ID, 25739261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana c.getString(COLUMN_GROUP_SOURCE_ID)); 25749261b2141aa90a4fed632fd6da03026d4c216280Fred Quintana } 25756cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov dataValues.put(RawContacts.Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 25767e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana for (int i = 0; i < 10; i++) { 25777e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int columnIndex = i + COLUMN_DATA1; 25787e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String key = DATA_KEYS[i]; 25797e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (c.isNull(columnIndex)) { 25807e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // don't put anything 25817e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isLong(columnIndex)) { 25827e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getLong(columnIndex)); 25837e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isFloat(columnIndex)) { 25847e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getFloat(columnIndex)); 25857e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isString(columnIndex)) { 25867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getString(columnIndex)); 25877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isBlob(columnIndex)) { 25887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getBlob(columnIndex)); 25897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25917e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contact.addSubValue(Data.CONTENT_URI, dataValues); 25927e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } while (mEntityCursor.moveToNext()); 25937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 25947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return contact; 25957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 25977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2598226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana /** 2599226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 2600226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 2601226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana */ 2602226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static class GroupsEntityIterator implements EntityIterator { 2603226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private final Cursor mEntityCursor; 2604226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private volatile boolean mIsClosed; 2605226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2606226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final String[] PROJECTION = new String[]{ 2607226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups._ID, 2608226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_NAME, 2609226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.ACCOUNT_TYPE, 2610226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.SOURCE_ID, 2611226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.DIRTY, 2612226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.VERSION, 2613226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.RES_PACKAGE, 2614226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE, 2615226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.TITLE_RES, 2616226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Groups.GROUP_VISIBLE}; 2617226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2618226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ID = 0; 2619226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_NAME = 1; 2620226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_ACCOUNT_TYPE = 2; 2621226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_SOURCE_ID = 3; 2622226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_DIRTY = 4; 2623226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_VERSION = 5; 2624226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_RES_PACKAGE = 6; 2625226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE = 7; 2626226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_TITLE_RES = 8; 2627226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana private static final int COLUMN_GROUP_VISIBLE = 9; 2628226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2629226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public GroupsEntityIterator(ContactsProvider2 provider, String groupIdString, Uri uri, 2630226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 2631226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = false; 2632226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2633226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String updatedSortOrder = (sortOrder == null) 2634226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ? Groups._ID 2635226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana : (Groups._ID + "," + sortOrder); 2636226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2637226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteDatabase db = provider.mOpenHelper.getReadableDatabase(); 2638226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 2639226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setTables(Tables.GROUPS_JOIN_PACKAGES); 2640226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.setProjectionMap(sGroupsProjectionMap); 2641226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (groupIdString != null) { 2642226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups._ID + "=" + groupIdString); 2643226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2644226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountName = uri.getQueryParameter(Groups.ACCOUNT_NAME); 2645226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final String accountType = uri.getQueryParameter(Groups.ACCOUNT_TYPE); 2646226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!TextUtils.isEmpty(accountName)) { 2647226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana qb.appendWhere(Groups.ACCOUNT_NAME + "=" 2648226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 2649226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + Groups.ACCOUNT_TYPE + "=" 2650226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 2651226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2652226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 2653226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana null, null, updatedSortOrder); 2654226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToFirst(); 2655226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2656226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2657226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public void close() { 2658226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 2659226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("closing when already closed"); 2660226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2661226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mIsClosed = true; 2662226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.close(); 2663226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2664226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2665226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public boolean hasNext() throws RemoteException { 2666226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 2667226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 2668226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2669226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2670226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return !mEntityCursor.isAfterLast(); 2671226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2672226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2673226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana public Entity next() throws RemoteException { 2674226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (mIsClosed) { 2675226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 2676226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2677226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (!hasNext()) { 2678226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 2679226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2680226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2681226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 2682226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2683226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana final long groupId = c.getLong(COLUMN_ID); 2684226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2685226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana // we expect the cursor is already at the row we need to read from 2686226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana ContentValues groupValues = new ContentValues(); 2687226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 2688226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 2689226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups._ID, groupId); 2690226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.DIRTY, c.getLong(COLUMN_DIRTY)); 2691226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.VERSION, c.getLong(COLUMN_VERSION)); 2692226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 2693226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.RES_PACKAGE, c.getString(COLUMN_RES_PACKAGE)); 2694226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE, c.getString(COLUMN_TITLE)); 2695226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.TITLE_RES, c.getString(COLUMN_TITLE_RES)); 2696226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana groupValues.put(Groups.GROUP_VISIBLE, c.getLong(COLUMN_GROUP_VISIBLE)); 2697226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana Entity group = new Entity(groupValues); 2698226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2699226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana mEntityCursor.moveToNext(); 2700226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2701226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return group; 2702226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2703226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2704226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2705a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 27067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs, 27077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String sortOrder) { 27087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int match = sUriMatcher.match(uri); 27097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana switch (match) { 27105ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: 27115ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: 27127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String contactsIdString = null; 27135ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov if (match == RAW_CONTACTS_ID) { 27147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contactsIdString = uri.getPathSegments().get(1); 27157e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 27167e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 27177e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return new ContactsEntityIterator(this, contactsIdString, 27187e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana uri, selection, selectionArgs, sortOrder); 2719226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS: 2720226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana case GROUPS_ID: 2721226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana String idString = null; 2722226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana if (match == GROUPS_ID) { 2723226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana idString = uri.getPathSegments().get(1); 2724226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana } 2725226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana 2726226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana return new GroupsEntityIterator(this, idString, 2727226c3dc6e93ca76a84c99100caa31045cba06cf6Fred Quintana uri, selection, selectionArgs, sortOrder); 27287e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana default: 27297e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new UnsupportedOperationException("Unknown uri: " + uri); 27307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 27317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 27327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 27334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 27344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 2735a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 27364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 2737d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS: return Contacts.CONTENT_TYPE; 2738d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case CONTACTS_ID: return Contacts.CONTENT_ITEM_TYPE; 27395ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS: return RawContacts.CONTENT_TYPE; 27405ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov case RAW_CONTACTS_ID: return RawContacts.CONTENT_ITEM_TYPE; 2741508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 27426bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 2743508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 2744b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey return mOpenHelper.getDataMimeType(dataId); 274531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: return AggregationExceptions.CONTENT_TYPE; 274631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_EXCEPTION_ID: return AggregationExceptions.CONTENT_ITEM_TYPE; 2747d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: return Contacts.CONTENT_TYPE; 2748c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SUGGESTIONS: 2749c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SUGGEST_MIME_TYPE; 2750c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov case SEARCH_SHORTCUT: 2751c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return SearchManager.SHORTCUT_MIME_TYPE; 27524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 2753a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton throw new UnsupportedOperationException("Unknown uri: " + uri); 27544f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 27557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 2756b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov @Override 27577e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 27587e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throws OperationApplicationException { 27597e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 27607e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 27617e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana db.beginTransaction(); 27627e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana try { 27637e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentProviderResult[] results = super.applyBatch(operations); 27647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana db.setTransactionSuccessful(); 27657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return results; 27667e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } finally { 27677e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana db.endTransaction(); 27687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 27697e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 2770c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 27715ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov private void setDisplayName(long rawContactId, String displayName) { 27723cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov if (displayName != null) { 27733cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mContactDisplayNameUpdate.bindString(1, displayName); 27743cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } else { 27753cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mContactDisplayNameUpdate.bindNull(1); 27763cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 27775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov mContactDisplayNameUpdate.bindLong(2, rawContactId); 27783cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov mContactDisplayNameUpdate.execute(); 27793cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov } 27803cebbf7141252768d3e272e049e9c5b0cb9d710eDmitri Plotnikov 2781c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 2782c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 2783c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 2784c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 2785c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 2786c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 2787c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private void setIsPrimary(long dataId) { 2788c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 2789c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(2, dataId); 2790c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(3, dataId); 2791c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 2792c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 2793c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 2794c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 2795c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 2796c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 2797c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 2798c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 2799c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 2800c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private void setIsSuperPrimary(long dataId) { 2801c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 2802c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(2, dataId); 2803c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(3, dataId); 2804c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 2805619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2806619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Find the parent aggregate and package for this new primary 2807619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 2808619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2809619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey long aggId = -1; 2810619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey boolean isRestricted = false; 2811619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey String mimeType = null; 2812619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2813619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey Cursor cursor = null; 2814619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey try { 2815d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov cursor = db.query(DataRawContactsQuery.TABLE, DataRawContactsQuery.PROJECTION, 281667dde51ab932dc84d95a203b113989b13437f13dJeff Sharkey DataColumns.CONCRETE_ID + "=" + dataId, null, null, null, null); 2817619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (cursor.moveToFirst()) { 2818d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov aggId = cursor.getLong(DataRawContactsQuery.CONTACT_ID); 2819d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov isRestricted = (cursor.getInt(DataRawContactsQuery.IS_RESTRICTED) == 1); 2820d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov mimeType = cursor.getString(DataRawContactsQuery.MIMETYPE); 2821619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2822619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } finally { 2823619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (cursor != null) { 2824619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey cursor.close(); 2825619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2826619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2827619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2828619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Bypass aggregate update if no parent found, or if we don't keep track 2829619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // of super-primary for this mimetype. 2830d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov if (aggId == -1) { 2831d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return; 2832d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 2833619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2834619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey boolean isPhone = CommonDataKinds.Phone.CONTENT_ITEM_TYPE.equals(mimeType); 2835619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey boolean isEmail = CommonDataKinds.Email.CONTENT_ITEM_TYPE.equals(mimeType); 2836619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2837619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Record this value as the new primary for the parent aggregate 2838619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final ContentValues values = new ContentValues(); 2839619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (isPhone) { 2840d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(ContactsColumns.OPTIMAL_PRIMARY_PHONE_ID, dataId); 2841d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(ContactsColumns.OPTIMAL_PRIMARY_PHONE_IS_RESTRICTED, isRestricted); 2842619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } else if (isEmail) { 2843d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(ContactsColumns.OPTIMAL_PRIMARY_EMAIL_ID, dataId); 2844d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(ContactsColumns.OPTIMAL_PRIMARY_EMAIL_IS_RESTRICTED, isRestricted); 2845619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2846619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2847619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // If this data is unrestricted, then also set as fallback 2848619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (!isRestricted && isPhone) { 2849d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(ContactsColumns.FALLBACK_PRIMARY_PHONE_ID, dataId); 2850619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } else if (!isRestricted && isEmail) { 2851d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov values.put(ContactsColumns.FALLBACK_PRIMARY_EMAIL_ID, dataId); 2852619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2853619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 2854d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov // Push update into contacts table, if needed 2855619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (values.size() > 0) { 2856d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov db.update(Tables.CONTACTS, values, Contacts._ID + "=" + aggId, null); 2857619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 2858c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 2859ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 2860d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov private String buildContactLookupWhereClause(String filterParam) { 2861ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar StringBuilder filter = new StringBuilder(); 2862d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov filter.append(Tables.CONTACTS); 2863ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append("."); 2864d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov filter.append(Contacts._ID); 2865ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append(" IN (SELECT "); 2866d3fde755e73cd3912a488e7cb7d412d3c5f6ca94Dmitri Plotnikov filter.append(RawContacts.CONTACT_ID); 2867ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append(" FROM "); 28685ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov filter.append(Tables.RAW_CONTACTS); 2869ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append(" WHERE "); 28706cffee46a1334d2b3ed19f436b27638451541044Dmitri Plotnikov filter.append(RawContacts._ID); 2871445ca81effbb0d61c7bc0033acf2d3dfd228fd4eDmitri Plotnikov filter.append(" IN "); 2872c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov appendRawContactsByFilterAsNestedQuery(filter, filterParam, null); 2873445ca81effbb0d61c7bc0033acf2d3dfd228fd4eDmitri Plotnikov filter.append(")"); 2874445ca81effbb0d61c7bc0033acf2d3dfd228fd4eDmitri Plotnikov return filter.toString(); 2875445ca81effbb0d61c7bc0033acf2d3dfd228fd4eDmitri Plotnikov } 2876445ca81effbb0d61c7bc0033acf2d3dfd228fd4eDmitri Plotnikov 28775ef0401c311c62e53bde415b99cbb0ff83b0a9a2Dmitri Plotnikov public String getRawContactsByFilterAsNestedQuery(String filterParam) { 2878c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov StringBuilder sb = new StringBuilder(); 2879c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov appendRawContactsByFilterAsNestedQuery(sb, filterParam, null); 2880c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov return sb.toString(); 2881c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 2882c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov 2883a908fb5f39aa2021662a6cc317cc7e4db2d8bfb0Dmitri Plotnikov public void appendRawContactsByFilterAsNestedQuery(StringBuilder sb, String filterParam, 2884c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov String limit) { 2885c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append("(SELECT DISTINCT raw_contact_id FROM name_lookup WHERE normalized_name GLOB '"); 2886c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(NameNormalizer.normalize(filterParam)); 2887c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append("*'"); 2888c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov if (limit != null) { 2889c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(" LIMIT ").append(limit); 2890c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov } 2891c70dc0e38ff82c6e6d6b7458637c54fbdf446aacDmitri Plotnikov sb.append(")"); 2892ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 2893ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 2894b67163a1088f09c59f324350662eb18772fac6b6Evan Millar private String[] appendGroupArg(String[] selectionArgs, String arg) { 2895b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 2896b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 2897b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 2898b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 2899b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 2900b67163a1088f09c59f324350662eb18772fac6b6Evan Millar System.arraycopy(selectionArgs, 0, newSelectionArgs, 0, selectionArgs.length); 2901b67163a1088f09c59f324350662eb18772fac6b6Evan Millar newSelectionArgs[newLength - 1] = arg; 2902b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 2903b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 2904b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 29054f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 2906