ContactsProvider2.java revision b67163a1088f09c59f324350662eb18772fac6b6
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 1928f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.AggregatesColumns; 2028f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.AggregationExceptionColumns; 2128f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.Clauses; 2228f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.ContactsColumns; 2328f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.ContactOptionsColumns; 2428f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.DataColumns; 2528f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.GroupsColumns; 2628f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.MimetypesColumns; 2728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.PhoneLookupColumns; 2828f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millarimport com.android.providers.contacts.OpenHelper.Tables; 2935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport com.android.internal.content.SyncStateContentProviderHelper; 304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 31b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.accounts.Account; 3235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.pm.PackageManager; 334f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.content.ContentProvider; 3435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.UriMatcher; 35b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkeyimport android.content.Context; 3635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentValues; 3735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentUris; 387e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport android.content.EntityIterator; 3935ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.Entity; 4035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentProviderResult; 417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport android.content.OperationApplicationException; 4235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintanaimport android.content.ContentProviderOperation; 434f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.Cursor; 44ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.database.DatabaseUtils; 45b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.database.sqlite.SQLiteCursor; 464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteDatabase; 474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.database.sqlite.SQLiteQueryBuilder; 48c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millarimport android.database.sqlite.SQLiteStatement; 494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamiltonimport android.net.Uri; 50619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.os.Binder; 51b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.os.RemoteException; 52508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkeyimport android.provider.BaseColumns; 53de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract; 546bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikovimport android.provider.Contacts.ContactMethods; 55de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.Aggregates; 56b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport android.provider.ContactsContract.AggregationExceptions; 57de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds; 58de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.Contacts; 59de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.Data; 60ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.Groups; 611f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkeyimport android.provider.ContactsContract.Presence; 62619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkeyimport android.provider.ContactsContract.RestrictionExceptions; 636bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikovimport android.provider.ContactsContract.Aggregates.AggregationSuggestions; 64ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email; 65ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.GroupMembership; 66de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millarimport android.provider.ContactsContract.CommonDataKinds.Phone; 67ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millarimport android.provider.ContactsContract.CommonDataKinds.Postal; 684097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 69a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.telephony.PhoneNumberUtils; 70a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamiltonimport android.text.TextUtils; 7100d71133c63c882fb41729ddc3a52f66fb155374Evan Millarimport android.util.Log; 724f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintanaimport java.util.ArrayList; 74b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikovimport java.util.HashMap; 754f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton/** 774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * Contacts content provider. The contract between this provider and applications 784f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton * is defined in {@link ContactsContract}. 794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton */ 80035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintanapublic class ContactsProvider2 extends ContentProvider { 81b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey // TODO: clean up debug tag and rename this class 82b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey private static final String TAG = "ContactsProvider ~~~~"; 834f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 84619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: define broadcastreceiver to catch app uninstalls that should clear exceptions 85619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: carefully prevent all incoming nested queries; they can be gaping security holes 86619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: check for restricted flag during insert(), update(), and delete() calls 87619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 88a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 90d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_ORDER_BY = Aggregates.STARRED + " DESC, " 91d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar + Aggregates.TIMES_CONTACTED + " DESC, " 92d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar + Aggregates.DISPLAY_NAME + " ASC"; 93d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final String STREQUENT_LIMIT = 94d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar "(SELECT COUNT(1) FROM " + Tables.AGGREGATES + " WHERE " 95d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar + Aggregates.STARRED + "=1) + 25"; 96d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 976bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int AGGREGATES = 1000; 986bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int AGGREGATES_ID = 1001; 996bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int AGGREGATES_DATA = 1002; 1001f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private static final int AGGREGATES_SUMMARY = 1003; 1011f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private static final int AGGREGATES_SUMMARY_ID = 1004; 102ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int AGGREGATES_SUMMARY_FILTER = 1005; 103d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final int AGGREGATES_SUMMARY_STREQUENT = 1006; 104d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar private static final int AGGREGATES_SUMMARY_STREQUENT_FILTER = 1007; 105b67163a1088f09c59f324350662eb18772fac6b6Evan Millar private static final int AGGREGATES_SUMMARY_GROUP = 1008; 1064f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1076bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int CONTACTS = 2002; 1086bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int CONTACTS_ID = 2003; 1096bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int CONTACTS_DATA = 2004; 11028ab0f857caa92402878244d9c5ea2a59e070935Jeff Sharkey private static final int CONTACTS_FILTER_EMAIL = 2005; 1114f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1126bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA = 3000; 1136bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int DATA_ID = 3001; 114ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES = 3002; 115ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int PHONES_FILTER = 3003; 116ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private static final int POSTALS = 3004; 117a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1186bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final int PHONE_LOOKUP = 4000; 1196bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 120b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTIONS = 6000; 121b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final int AGGREGATION_EXCEPTION_ID = 6001; 122b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 1231f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private static final int PRESENCE = 7000; 1241f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private static final int PRESENCE_ID = 7001; 1251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 12631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int AGGREGATION_SUGGESTIONS = 8000; 12731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 128619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private static final int RESTRICTION_EXCEPTIONS = 9000; 129619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 130ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS = 10000; 131ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_ID = 10001; 132ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final int GROUPS_SUMMARY = 10003; 133ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 13435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana private static final int SYNCSTATE = 11000; 13535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 136ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private interface Projections { 137ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final String[] PROJ_CONTACTS = new String[] { 138ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContactsColumns.CONCRETE_ID, 139ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 140ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 141ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final String[] PROJ_DATA_CONTACTS = new String[] { 142ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContactsColumns.CONCRETE_ID, 143ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey DataColumns.CONCRETE_ID, 144ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Contacts.AGGREGATE_ID, 145ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContactsColumns.PACKAGE_ID, 146ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Contacts.IS_RESTRICTED, 147ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Data.MIMETYPE, 148ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 149ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 150ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int COL_CONTACT_ID = 0; 151ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int COL_DATA_ID = 1; 152ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int COL_AGGREGATE_ID = 2; 153ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int COL_PACKAGE_ID = 3; 154ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int COL_IS_RESTRICTED = 4; 155ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int COL_MIMETYPE = 5; 156ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 157ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final String[] PROJ_DATA_AGGREGATES = new String[] { 158ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContactsColumns.CONCRETE_ID, 159ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey DataColumns.CONCRETE_ID, 160ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey AggregatesColumns.CONCRETE_ID, 161ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey MimetypesColumns.CONCRETE_ID, 162ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Phone.NUMBER, 163ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Email.DATA, 164ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey AggregatesColumns.OPTIMAL_PRIMARY_PHONE_ID, 165ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey AggregatesColumns.FALLBACK_PRIMARY_PHONE_ID, 166ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey AggregatesColumns.OPTIMAL_PRIMARY_EMAIL_ID, 167ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey AggregatesColumns.FALLBACK_PRIMARY_EMAIL_ID, 168ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 169ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 170ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int COL_MIMETYPE_ID = 3; 171ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int COL_PHONE_NUMBER = 4; 172ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int COL_EMAIL_DATA = 5; 173ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int COL_OPTIMAL_PHONE_ID = 6; 174ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int COL_FALLBACK_PHONE_ID = 7; 175ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int COL_OPTIMAL_EMAIL_ID = 8; 176ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey public static final int COL_FALLBACK_EMAIL_ID = 9; 17780c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 178ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1791f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 18031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /** Default for the maximum number of returned aggregation suggestions. */ 18131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov private static final int DEFAULT_MAX_SUGGESTIONS = 5; 18231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1836bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** Contains just the contacts columns */ 1846bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private static final HashMap<String, String> sAggregatesProjectionMap; 18500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar /** Contains the aggregate columns along with primary phone */ 1861f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private static final HashMap<String, String> sAggregatesSummaryProjectionMap; 187de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millar /** Contains the data, contacts, and aggregate columns, for joined tables. */ 188de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millar private static final HashMap<String, String> sDataContactsAggregateProjectionMap; 189a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** Contains just the contacts columns */ 1904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sContactsProjectionMap; 191a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** Contains just the data columns */ 1924f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private static final HashMap<String, String> sDataProjectionMap; 193a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** Contains the data and contacts columns, for joined tables */ 194a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private static final HashMap<String, String> sDataContactsProjectionMap; 195ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains the just the {@link Groups} columns */ 196ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsProjectionMap; 197ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** Contains {@link Groups} columns along with summary details */ 198ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private static final HashMap<String, String> sGroupsSummaryProjectionMap; 199b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov /** Contains the just the agg_exceptions columns */ 200b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov private static final HashMap<String, String> sAggregationExceptionsProjectionMap; 201619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** Contains the just the {@link RestrictionExceptions} columns */ 202619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private static final HashMap<String, String> sRestrictionExceptionsProjectionMap; 2037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 204c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Sql select statement that returns the contact id associated with a data record. */ 205c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private static final String sNestedContactIdSelect; 206c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Sql select statement that returns the mimetype id associated with a data record. */ 207c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private static final String sNestedMimetypeSelect; 208c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Sql select statement that returns the aggregate id associated with a contact record. */ 209c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private static final String sNestedAggregateIdSelect; 210c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Sql select statement that returns a list of contact ids associated with an aggregate record. */ 211c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private static final String sNestedContactIdListSelect; 212c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Sql where statement used to match all the data records that need to be updated when a new 213c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * "primary" is selected.*/ 214c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private static final String sSetPrimaryWhere; 215c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Sql where statement used to match all the data records that need to be updated when a new 216c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * "super primary" is selected.*/ 217c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private static final String sSetSuperPrimaryWhere; 218b67163a1088f09c59f324350662eb18772fac6b6Evan Millar /** Sql where statement for filtering on groups. */ 219b67163a1088f09c59f324350662eb18772fac6b6Evan Millar private static final String sAggregatesInGroupSelect; 220c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precompiled sql statement for setting a data record to the primary. */ 221c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetPrimaryStatement; 222c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /** Precomipled sql statement for setting a data record to the super primary. */ 223c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private SQLiteStatement mSetSuperPrimaryStatement; 224a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 2251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private static final String GTALK_PROTOCOL_STRING = ContactMethods 2261f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey .encodePredefinedImProtocol(ContactMethods.PROTOCOL_GOOGLE_TALK); 2271f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 2284f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton static { 2294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts URI matching table 230a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final UriMatcher matcher = sUriMatcher; 2316bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregates", AGGREGATES); 2326bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregates/#", AGGREGATES_ID); 2336bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregates/#/data", AGGREGATES_DATA); 2341f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "aggregates_summary", AGGREGATES_SUMMARY); 2351f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "aggregates_summary/#", AGGREGATES_SUMMARY_ID); 236ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "aggregates_summary/filter/*", 237ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar AGGREGATES_SUMMARY_FILTER); 238d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "aggregates_summary/strequent/", 239d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar AGGREGATES_SUMMARY_STREQUENT); 240d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "aggregates_summary/strequent/filter/*", 241d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar AGGREGATES_SUMMARY_STREQUENT_FILTER); 242b67163a1088f09c59f324350662eb18772fac6b6Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "aggregates_summary/group/*", 243b67163a1088f09c59f324350662eb18772fac6b6Evan Millar AGGREGATES_SUMMARY_GROUP); 24431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregates/#/suggestions", 24531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov AGGREGATION_SUGGESTIONS); 2464f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS); 2474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID); 248a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_DATA); 249b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter_email/*", 250b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov CONTACTS_FILTER_EMAIL); 251b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 2524f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); 2534f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); 254ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); 255ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER); 256ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "data/postals", POSTALS); 2571f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 258ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups", GROUPS); 259ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups/#", GROUPS_ID); 260ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "groups_summary", GROUPS_SUMMARY); 261ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 26235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana matcher.addURI(ContactsContract.AUTHORITY, SyncStateContentProviderHelper.PATH, SYNCSTATE); 26335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 264a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton matcher.addURI(ContactsContract.AUTHORITY, "phone_lookup/*", PHONE_LOOKUP); 265b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions", 266b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTIONS); 267b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov matcher.addURI(ContactsContract.AUTHORITY, "aggregation_exceptions/*", 268b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov AGGREGATION_EXCEPTION_ID); 2694f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 270bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "presence", PRESENCE); 271bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar matcher.addURI(ContactsContract.AUTHORITY, "presence/#", PRESENCE_ID); 2721f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 273619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey matcher.addURI(ContactsContract.AUTHORITY, "restriction_exceptions", RESTRICTION_EXCEPTIONS); 274619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 275fec4e13316f2731d84394e5fa2f93af3febdc20cEvan Millar HashMap<String, String> columns; 2764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 2776bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov // Aggregates projection map 2786bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov columns = new HashMap<String, String>(); 27900d71133c63c882fb41729ddc3a52f66fb155374Evan Millar columns.put(Aggregates._ID, "aggregates._id AS _id"); 2806bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov columns.put(Aggregates.DISPLAY_NAME, Aggregates.DISPLAY_NAME); 2816bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov columns.put(Aggregates.LAST_TIME_CONTACTED, Aggregates.LAST_TIME_CONTACTED); 282d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar columns.put(Aggregates.TIMES_CONTACTED, Aggregates.TIMES_CONTACTED); 2836bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov columns.put(Aggregates.STARRED, Aggregates.STARRED); 284ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Aggregates.IN_VISIBLE_GROUP, Aggregates.IN_VISIBLE_GROUP); 285ae6ca1f34cf5458d79ec803411d4308879a91e92Evan Millar columns.put(Aggregates.PHOTO_ID, Aggregates.PHOTO_ID); 286de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millar columns.put(Aggregates.PRIMARY_PHONE_ID, Aggregates.PRIMARY_PHONE_ID); 287c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar columns.put(Aggregates.PRIMARY_EMAIL_ID, Aggregates.PRIMARY_EMAIL_ID); 288d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov columns.put(Aggregates.CUSTOM_RINGTONE, Aggregates.CUSTOM_RINGTONE); 289d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov columns.put(Aggregates.SEND_TO_VOICEMAIL, Aggregates.SEND_TO_VOICEMAIL); 290619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey columns.put(AggregatesColumns.FALLBACK_PRIMARY_PHONE_ID, 291619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey AggregatesColumns.FALLBACK_PRIMARY_PHONE_ID); 292619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey columns.put(AggregatesColumns.FALLBACK_PRIMARY_EMAIL_ID, 293619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey AggregatesColumns.FALLBACK_PRIMARY_EMAIL_ID); 2946bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov sAggregatesProjectionMap = columns; 2956bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 2961f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // Aggregates primaries projection map. The overall presence status is 2971f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // the most-present value, as indicated by the largest value. 2981f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey columns = new HashMap<String, String>(); 2991f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey columns.putAll(sAggregatesProjectionMap); 30000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar columns.put(CommonDataKinds.Phone.TYPE, CommonDataKinds.Phone.TYPE); 30100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar columns.put(CommonDataKinds.Phone.LABEL, CommonDataKinds.Phone.LABEL); 30200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar columns.put(CommonDataKinds.Phone.NUMBER, CommonDataKinds.Phone.NUMBER); 303bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar columns.put(Presence.PRESENCE_STATUS, "MAX(" + Presence.PRESENCE_STATUS + ")"); 3041f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey sAggregatesSummaryProjectionMap = columns; 30500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 3064f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Contacts projection map 3074f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton columns = new HashMap<String, String>(); 3084f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton columns.put(Contacts._ID, "contacts._id AS _id"); 309619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey columns.put(Contacts.PACKAGE, Contacts.PACKAGE); 3106bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov columns.put(Contacts.AGGREGATE_ID, Contacts.AGGREGATE_ID); 311035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Contacts.ACCOUNT_NAME, Contacts.ACCOUNT_NAME); 312035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Contacts.ACCOUNT_TYPE, Contacts.ACCOUNT_TYPE); 3137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Contacts.SOURCE_ID, Contacts.SOURCE_ID); 3147e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Contacts.VERSION, Contacts.VERSION); 3157e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Contacts.DIRTY, Contacts.DIRTY); 3164f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton sContactsProjectionMap = columns; 3174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 3184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Data projection map 3194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton columns = new HashMap<String, String>(); 3204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton columns.put(Data._ID, "data._id AS _id"); 3214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton columns.put(Data.CONTACT_ID, Data.CONTACT_ID); 322508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey columns.put(Data.MIMETYPE, Data.MIMETYPE); 323c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar columns.put(Data.IS_PRIMARY, Data.IS_PRIMARY); 324c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar columns.put(Data.IS_SUPER_PRIMARY, Data.IS_SUPER_PRIMARY); 325f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana columns.put(Data.DATA_VERSION, Data.DATA_VERSION); 3267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA1, "data.data1 as data1"); 3277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA2, "data.data2 as data2"); 3287e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA3, "data.data3 as data3"); 3297e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA4, "data.data4 as data4"); 3307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA5, "data.data5 as data5"); 3317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA6, "data.data6 as data6"); 3327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA7, "data.data7 as data7"); 3337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA8, "data.data8 as data8"); 3347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA9, "data.data9 as data9"); 3357e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.put(Data.DATA10, "data.data10 as data10"); 336d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Mappings used for backwards compatibility. 337d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar columns.put("number", Phone.NUMBER); 3384f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton sDataProjectionMap = columns; 339a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 340a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Data and contacts projection map for joins. _id comes from the data table 341a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton columns = new HashMap<String, String>(); 342a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton columns.putAll(sContactsProjectionMap); 343a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton columns.putAll(sDataProjectionMap); // _id will be replaced with the one from data 344ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Data.CONTACT_ID, DataColumns.CONCRETE_CONTACT_ID); 345a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton sDataContactsProjectionMap = columns; 3467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 347de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millar // Data and contacts projection map for joins. _id comes from the data table 348de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millar columns = new HashMap<String, String>(); 349de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millar columns.putAll(sAggregatesProjectionMap); 3507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana columns.putAll(sContactsProjectionMap); // 351de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millar columns.putAll(sDataProjectionMap); // _id will be replaced with the one from data 352ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Data.CONTACT_ID, DataColumns.CONCRETE_CONTACT_ID); 353de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millar sDataContactsAggregateProjectionMap = columns; 354c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 355ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Groups projection map 356ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 357ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups._ID, "groups._id AS _id"); 358035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_NAME, Groups.ACCOUNT_NAME); 359035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana columns.put(Groups.ACCOUNT_TYPE, Groups.ACCOUNT_TYPE); 360ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.PACKAGE, Groups.PACKAGE); 361ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.PACKAGE_ID, GroupsColumns.CONCRETE_PACKAGE_ID); 362ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE, Groups.TITLE); 363ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.TITLE_RESOURCE, Groups.TITLE_RESOURCE); 364ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.GROUP_VISIBLE, Groups.GROUP_VISIBLE); 365ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsProjectionMap = columns; 366ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 367ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Contacts and groups projection map 368ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns = new HashMap<String, String>(); 369ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.putAll(sGroupsProjectionMap); 370ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 371ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_COUNT, "(SELECT COUNT(DISTINCT " + AggregatesColumns.CONCRETE_ID 372ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") FROM " + Tables.DATA_JOIN_MIMETYPES_CONTACTS_AGGREGATES + " WHERE " 373ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 374ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + ") AS " + Groups.SUMMARY_COUNT); 375ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 376ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey columns.put(Groups.SUMMARY_WITH_PHONES, "(SELECT COUNT(DISTINCT " 377ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + AggregatesColumns.CONCRETE_ID + ") FROM " 378ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Tables.DATA_JOIN_MIMETYPES_CONTACTS_AGGREGATES + " WHERE " 379ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + Clauses.MIMETYPE_IS_GROUP_MEMBERSHIP + " AND " + Clauses.BELONGS_TO_GROUP 380ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + " AND " + Clauses.HAS_PRIMARY_PHONE + ") AS " + Groups.SUMMARY_WITH_PHONES); 381ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 382ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey sGroupsSummaryProjectionMap = columns; 383ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 384b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov // Aggregate exception projection map 385b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns = new HashMap<String, String>(); 386b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptionColumns._ID, Tables.AGGREGATION_EXCEPTIONS + "._id AS _id"); 387b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov columns.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE); 388127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov columns.put(AggregationExceptions.AGGREGATE_ID, 389127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov "contacts1." + Contacts.AGGREGATE_ID + " AS " + AggregationExceptions.AGGREGATE_ID); 390127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov columns.put(AggregationExceptions.CONTACT_ID, AggregationExceptionColumns.CONTACT_ID2); 391b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov sAggregationExceptionsProjectionMap = columns; 392b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 393619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Restriction exception projection map 394619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey columns = new HashMap<String, String>(); 395619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey columns.put(RestrictionExceptions.PACKAGE_PROVIDER, RestrictionExceptions.PACKAGE_PROVIDER); 396619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey columns.put(RestrictionExceptions.PACKAGE_CLIENT, RestrictionExceptions.PACKAGE_CLIENT); 397619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey columns.put(RestrictionExceptions.ALLOW_ACCESS, "1"); // Access granted if row returned 398619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey sRestrictionExceptionsProjectionMap = columns; 399619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 400c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar sNestedContactIdSelect = "SELECT " + Data.CONTACT_ID + " FROM " + Tables.DATA + " WHERE " 401c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + Data._ID + "=?"; 402c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar sNestedMimetypeSelect = "SELECT " + DataColumns.MIMETYPE_ID + " FROM " + Tables.DATA 403c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + " WHERE " + Data._ID + "=?"; 404c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar sNestedAggregateIdSelect = "SELECT " + Contacts.AGGREGATE_ID + " FROM " + Tables.CONTACTS 405c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + " WHERE " + Contacts._ID + "=(" + sNestedContactIdSelect + ")"; 406c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar sNestedContactIdListSelect = "SELECT " + Contacts._ID + " FROM " + Tables.CONTACTS 407c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + " WHERE " + Contacts.AGGREGATE_ID + "=(" + sNestedAggregateIdSelect + ")"; 408c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar sSetPrimaryWhere = Data.CONTACT_ID + "=(" + sNestedContactIdSelect + ") AND " 409c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + DataColumns.MIMETYPE_ID + "=(" + sNestedMimetypeSelect + ")"; 410b67163a1088f09c59f324350662eb18772fac6b6Evan Millar sSetSuperPrimaryWhere = Data.CONTACT_ID + " IN (" + sNestedContactIdListSelect + ") AND " 411c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + DataColumns.MIMETYPE_ID + "=(" + sNestedMimetypeSelect + ")"; 412b67163a1088f09c59f324350662eb18772fac6b6Evan Millar sAggregatesInGroupSelect = AggregatesColumns.CONCRETE_ID + " IN (SELECT " 413b67163a1088f09c59f324350662eb18772fac6b6Evan Millar + Contacts.AGGREGATE_ID + " FROM " + Tables.CONTACTS + " WHERE (" 414b67163a1088f09c59f324350662eb18772fac6b6Evan Millar + ContactsColumns.CONCRETE_ID + " IN (SELECT " + Tables.DATA + "." 415b67163a1088f09c59f324350662eb18772fac6b6Evan Millar + Data.CONTACT_ID + " FROM " + Tables.DATA_JOIN_MIMETYPES + " WHERE (" 416b67163a1088f09c59f324350662eb18772fac6b6Evan Millar + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE + "' AND " 417b67163a1088f09c59f324350662eb18772fac6b6Evan Millar + GroupMembership.GROUP_ROW_ID + "=(SELECT " + Tables.GROUPS + "." 418b67163a1088f09c59f324350662eb18772fac6b6Evan Millar + Groups._ID + " FROM " + Tables.GROUPS + " WHERE " + Groups.TITLE + "=?)))))"; 4194f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 4204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 42153056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov private final ContactAggregationScheduler mAggregationScheduler; 4224f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton private OpenHelper mOpenHelper; 42331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 424a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov private ContactAggregator mContactAggregator; 4254097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private NameSplitter mNameSplitter; 426a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 427a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov public ContactsProvider2() { 42853056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov this(new ContactAggregationScheduler()); 429a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 430a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 431a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 432a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Constructor for testing. 433a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 43453056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov /* package */ ContactsProvider2(ContactAggregationScheduler scheduler) { 43553056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov mAggregationScheduler = scheduler; 436a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 4374f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 4384f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 4394f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean onCreate() { 440b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey final Context context = getContext(); 44135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 44231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov mOpenHelper = getOpenHelper(context); 4431f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 4444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 44553056d49d8adf5d1fe2d18cb60c3c26f281e7a6cDmitri Plotnikov mContactAggregator = new ContactAggregator(context, mOpenHelper, mAggregationScheduler); 446a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 447c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement = db.compileStatement( 448c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar "UPDATE " + Tables.DATA + " SET " + Data.IS_PRIMARY 449c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + "=(_id=?) WHERE " + sSetPrimaryWhere); 450c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement = db.compileStatement( 451c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar "UPDATE " + Tables.DATA + " SET " + Data.IS_SUPER_PRIMARY 452c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar + "=(_id=?) WHERE " + sSetSuperPrimaryWhere); 453a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 45428f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar mNameSplitter = new NameSplitter( 45528f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_prefixes), 45628f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_last_name_prefixes), 45728f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_suffixes), 45828f8857b1b46bde18b85c6d3c2a63ac44c3c2e1cEvan Millar context.getString(com.android.internal.R.string.common_name_conjunctions)); 4594097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 4601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return (db != null); 4614f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 4624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 46331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov /* Visible for testing */ 46431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov protected OpenHelper getOpenHelper(final Context context) { 46531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov return OpenHelper.getInstance(context); 46631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 46731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 468a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 469a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov protected void finalize() throws Throwable { 470a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov if (mContactAggregator != null) { 471a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mContactAggregator.quit(); 472a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 473a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 474a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov super.finalize(); 475a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 476a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 477a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 478a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov * Wipes all data from the contacts database. 479a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov */ 480a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /* package */ void wipeData() { 481a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mOpenHelper.wipeData(); 482a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 483a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 484a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 485a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Called when a change has been made. 486a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 487a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param uri the uri that the change was made to 488a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 489a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton private void onChange(Uri uri) { 490a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null); 491a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 492a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 4934f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 4944f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public boolean isTemporary() { 4954f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return false; 4964f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 4974f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 4984f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 4994f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Uri insert(Uri uri, ContentValues values) { 500a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 501a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 50235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 503a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton switch (match) { 50435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 50535ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana id = mOpenHelper.getSyncState().insert(mOpenHelper.getWritableDatabase(), values); 50635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana break; 50735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 5086bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov case AGGREGATES: { 5096bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov id = insertAggregate(values); 5106bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 5116bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 5126bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 513a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case CONTACTS: { 514f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana final Account account = readAccountFromQueryParams(uri); 515f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana id = insertContact(values, account); 516a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 517a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 518a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 519a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case CONTACTS_DATA: { 520a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton values.put(Data.CONTACT_ID, uri.getPathSegments().get(1)); 521035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana id = insertData(values); 522a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 523a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 524a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 525a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case DATA: { 526035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana id = insertData(values); 527a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 528a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 529a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 530ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 531ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final Account account = readAccountFromQueryParams(uri); 532ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey id = insertGroup(values, account); 533ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 534ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 535ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 5361f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey case PRESENCE: { 5371f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey id = insertPresence(values); 5381f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 5391f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 5401f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 541a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton default: 542508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey throw new UnsupportedOperationException("Unknown uri: " + uri); 543a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 544a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 5457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (id < 0) { 5467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return null; 5477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 5487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 5497e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final Uri result = ContentUris.withAppendedId(uri, id); 550a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton onChange(result); 551a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return result; 552a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 553a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 554a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 555035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * If account is non-null then store it in the values. If the account is already 556035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * specified in the values then it must be consistent with the account, if it is non-null. 557035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param values the ContentValues to read from and update 558035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @param account the explicitly provided Account 559035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana * @return false if the accounts are inconsistent 5607e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 561035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private boolean resolveAccount(ContentValues values, Account account) { 562035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana // If either is specified then both must be specified. 563035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final String accountName = values.getAsString(Contacts.ACCOUNT_NAME); 564035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final String accountType = values.getAsString(Contacts.ACCOUNT_TYPE); 565035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName) || !TextUtils.isEmpty(accountType)) { 566035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final Account valuesAccount = new Account(accountName, accountType); 567035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null && !valuesAccount.equals(account)) { 568035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return false; 569035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 570035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana account = valuesAccount; 571035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 572035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (account != null) { 573035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana values.put(Contacts.ACCOUNT_NAME, account.mName); 574035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana values.put(Contacts.ACCOUNT_TYPE, account.mType); 575035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 576035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana return true; 5777e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 5787e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 5797e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 5806bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * Inserts an item in the aggregates table 5816bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * 5826bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @param values the values for the new row 5836bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * @return the row ID of the newly created row 5846bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 5856bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov private long insertAggregate(ContentValues values) { 586a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov throw new UnsupportedOperationException("Aggregates are created automatically"); 5876bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 5886bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 5896bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /** 590a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the contacts table 591a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 592a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 593f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana * @param account the account this contact should be associated with. may be null. 594a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 595a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 596f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana private long insertContact(ContentValues values, Account account) { 5976bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov /* 5986bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * The contact record is inserted in the contacts table, but it needs to 5996bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * be processed by the aggregator before it will be returned by the 6006bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov * "aggregates" queries. 6016bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov */ 602a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 6036bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 604a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov ContentValues overriddenValues = new ContentValues(values); 605a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov overriddenValues.putNull(Contacts.AGGREGATE_ID); 606f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana if (!resolveAccount(overriddenValues, account)) { 6077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return -1; 6087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 6097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 610619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Replace package with internal mapping 611619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final String packageName = overriddenValues.getAsString(Contacts.PACKAGE); 612619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey overriddenValues.put(ContactsColumns.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 613619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey overriddenValues.remove(Contacts.PACKAGE); 614619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 615a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov long rowId = db.insert(Tables.CONTACTS, Contacts.AGGREGATE_ID, overriddenValues); 616a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 617a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mContactAggregator.schedule(); 618a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 619a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov return rowId; 620a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 621a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 622a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton /** 623a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * Inserts an item in the data table 624a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * 625a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @param values the values for the new row 626a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton * @return the row ID of the newly created row 627a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton */ 628035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private long insertData(ContentValues values) { 629a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov boolean success = false; 630a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 631a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 632a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton long id = 0; 633a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton db.beginTransaction(); 634a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton try { 635a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov long contactId = values.getAsLong(Data.CONTACT_ID); 636a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 637619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Replace mimetype with internal mapping 638508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final String mimeType = values.getAsString(Data.MIMETYPE); 639b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey values.put(DataColumns.MIMETYPE_ID, mOpenHelper.getMimeTypeId(mimeType)); 640508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey values.remove(Data.MIMETYPE); 641508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 6424097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) { 6434097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov parseStructuredName(values); 6444097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov } 6454097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 646508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey // Insert the data row itself 647b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey id = db.insert(Tables.DATA, Data.DATA1, values); 648508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 649a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // If it's a phone number add the normalized version to the lookup table 6504097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) { 651508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final ContentValues phoneValues = new ContentValues(); 652508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final String number = values.getAsString(Phone.NUMBER); 653508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, 654508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey PhoneNumberUtils.getStrippedReversed(number)); 655508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey phoneValues.put(PhoneLookupColumns.DATA_ID, id); 656a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov phoneValues.put(PhoneLookupColumns.CONTACT_ID, contactId); 657b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey db.insert(Tables.PHONE_LOOKUP, null, phoneValues); 658a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 659a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 6606bccc079d8fea5c51f9fa6fd06044bd8f5109c6fDmitri Plotnikov mContactAggregator.markContactForAggregation(contactId); 661a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 662a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton db.setTransactionSuccessful(); 663a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov success = true; 664a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } finally { 665a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton db.endTransaction(); 666a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 667a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 668a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov if (success) { 669a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov mContactAggregator.schedule(); 670a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov } 671a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov 672a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton return id; 6734f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 6744f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 675a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov /** 676ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Delete the given {@link Data} row, fixing up any {@link Aggregates} 677ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * primaries that reference it. 678ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 679ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private int deleteData(long dataId) { 680ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 681ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 682ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final long mimePhone = mOpenHelper.getMimeTypeId(Phone.CONTENT_ITEM_TYPE); 683ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final long mimeEmail = mOpenHelper.getMimeTypeId(Email.CONTENT_ITEM_TYPE); 684ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 685ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Check to see if the data about to be deleted was a super-primary on 686ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // the parent aggregate, and set flags to fix-up once deleted. 687ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long aggId = -1; 688ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long mimeId = -1; 689ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey String dataRaw = null; 690ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey boolean fixOptimal = false; 691ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey boolean fixFallback = false; 692ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 693ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Cursor cursor = null; 694ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey try { 695ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor = db.query(Tables.DATA_JOIN_MIMETYPES_CONTACTS_AGGREGATES, 696ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Projections.PROJ_DATA_AGGREGATES, DataColumns.CONCRETE_ID + "=" + dataId, null, 697ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey null, null, null); 698ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (cursor.moveToFirst()) { 699ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey aggId = cursor.getLong(Projections.COL_AGGREGATE_ID); 700ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey mimeId = cursor.getLong(Projections.COL_MIMETYPE_ID); 701ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (mimeId == mimePhone) { 702ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey dataRaw = cursor.getString(Projections.COL_PHONE_NUMBER); 703ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey fixOptimal = (cursor.getLong(Projections.COL_OPTIMAL_PHONE_ID) == dataId); 704ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey fixFallback = (cursor.getLong(Projections.COL_FALLBACK_PHONE_ID) == dataId); 705ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } else if (mimeId == mimeEmail) { 706ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey dataRaw = cursor.getString(Projections.COL_EMAIL_DATA); 707ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey fixOptimal = (cursor.getLong(Projections.COL_OPTIMAL_EMAIL_ID) == dataId); 708ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey fixFallback = (cursor.getLong(Projections.COL_FALLBACK_EMAIL_ID) == dataId); 709ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 710ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 711ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } finally { 712ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (cursor != null) { 713ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor.close(); 714ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor = null; 715ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 716ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 717ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 718ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Delete the requested data item. 719ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey int dataDeleted = db.delete(Tables.DATA, Data._ID + "=" + dataId, null); 720ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 721ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Fix-up any super-primary values that are now invalid. 722ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (fixOptimal || fixFallback) { 723ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final ContentValues values = new ContentValues(); 724ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final StringBuilder scoreClause = new StringBuilder(); 725ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 726ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final String SCORE = "score"; 727ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 728ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Build scoring clause that will first pick data items under the 729ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // same aggregate that have identical values, otherwise fall back to 730ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // normal primary scoring from the member contacts. 731ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.append("(CASE WHEN "); 732ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (mimeId == mimePhone) { 733ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.append(Phone.NUMBER); 734ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } else if (mimeId == mimeEmail) { 735ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.append(Email.DATA); 736ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 737ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.append("="); 738ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey DatabaseUtils.appendEscapedSQLString(scoreClause, dataRaw); 739ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.append(" THEN 2 ELSE " + Data.IS_PRIMARY + " END) AS " + SCORE); 740ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 741ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final String[] PROJ_PRIMARY = new String[] { 742ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey DataColumns.CONCRETE_ID, 743ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Contacts.IS_RESTRICTED, 744ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContactsColumns.PACKAGE_ID, 745ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey scoreClause.toString(), 746ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey }; 747ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 748ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final int COL_DATA_ID = 0; 749ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final int COL_IS_RESTRICTED = 1; 750ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final int COL_PACKAGE_ID = 2; 751ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final int COL_SCORE = 3; 752ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 753ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor = db.query(Tables.DATA_JOIN_MIMETYPES_CONTACTS_AGGREGATES, PROJ_PRIMARY, 754ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey AggregatesColumns.CONCRETE_ID + "=" + aggId + " AND " + DataColumns.MIMETYPE_ID 755ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + "=" + mimeId, null, null, null, SCORE); 756ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 757ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (fixOptimal) { 758ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey String colId = null; 759ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey String colPackageId = null; 760ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (mimeId == mimePhone) { 761ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey colId = AggregatesColumns.OPTIMAL_PRIMARY_PHONE_ID; 762ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey colPackageId = AggregatesColumns.OPTIMAL_PRIMARY_PHONE_PACKAGE_ID; 763ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } else if (mimeId == mimeEmail) { 764ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey colId = AggregatesColumns.OPTIMAL_PRIMARY_EMAIL_ID; 765ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey colPackageId = AggregatesColumns.OPTIMAL_PRIMARY_EMAIL_PACKAGE_ID; 766ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 767ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 768ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Start by replacing with null, since fixOptimal told us that 769ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // the previous aggregate values are bad. 770ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.putNull(colId); 771ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.putNull(colPackageId); 772ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 773ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // When finding a new optimal primary, we only care about the 774ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // highest scoring value, regardless of source. 775ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (cursor.moveToFirst()) { 776ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final long newOptimal = cursor.getLong(COL_DATA_ID); 777ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final long newOptimalPackage = cursor.getLong(COL_PACKAGE_ID); 778ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 779ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (newOptimal != 0) { 780ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(colId, newOptimal); 781ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 782ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (newOptimalPackage != 0) { 783ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(colPackageId, newOptimalPackage); 784ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 785ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 786ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 787ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 788ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (fixFallback) { 789ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey String colId = null; 790ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (mimeId == mimePhone) { 791ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey colId = AggregatesColumns.FALLBACK_PRIMARY_PHONE_ID; 792ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } else if (mimeId == mimeEmail) { 793ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey colId = AggregatesColumns.FALLBACK_PRIMARY_EMAIL_ID; 794ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 795ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 796ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Start by replacing with null, since fixFallback told us that 797ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // the previous aggregate values are bad. 798ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.putNull(colId); 799ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 800ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // The best fallback value is the highest scoring data item that 801ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // hasn't been restricted. 802ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor.moveToPosition(-1); 803ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey while (cursor.moveToNext()) { 804ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final boolean isRestricted = (cursor.getInt(COL_IS_RESTRICTED) == 1); 805ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!isRestricted) { 806ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey values.put(colId, cursor.getLong(COL_DATA_ID)); 807ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 808ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 809ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 810ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 811ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 812ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Push through any aggregate updates we have 813ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (values.size() > 0) { 814ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey db.update(Tables.AGGREGATES, values, AggregatesColumns.CONCRETE_ID + "=" + aggId, 815ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey null); 816ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 817ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 818ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 819ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return dataDeleted; 820ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 821ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 822ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 8234097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov * Parse the supplied display name, but only if the incoming values do not already contain 8244097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov * structured name parts. 8254097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov */ 8264097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov private void parseStructuredName(ContentValues values) { 8274097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov final String fullName = values.getAsString(StructuredName.DISPLAY_NAME); 8284097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov if (TextUtils.isEmpty(fullName) 8294097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov || !TextUtils.isEmpty(values.getAsString(StructuredName.PREFIX)) 8304097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov || !TextUtils.isEmpty(values.getAsString(StructuredName.GIVEN_NAME)) 8314097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov || !TextUtils.isEmpty(values.getAsString(StructuredName.MIDDLE_NAME)) 8324097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov || !TextUtils.isEmpty(values.getAsString(StructuredName.FAMILY_NAME)) 8334097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov || !TextUtils.isEmpty(values.getAsString(StructuredName.SUFFIX))) { 8344097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov return; 8354097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov } 8364097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 8374097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov NameSplitter.Name name = new NameSplitter.Name(); 8384097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov mNameSplitter.split(name, fullName); 8394097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 8404097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov values.put(StructuredName.PREFIX, name.getPrefix()); 8414097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov values.put(StructuredName.GIVEN_NAME, name.getGivenNames()); 8424097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov values.put(StructuredName.MIDDLE_NAME, name.getMiddleName()); 8434097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov values.put(StructuredName.FAMILY_NAME, name.getFamilyName()); 8444097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov values.put(StructuredName.SUFFIX, name.getSuffix()); 8454097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov } 8464097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov 8474097855e2d672b3f8e1c5c8a169efb80203bf53eDmitri Plotnikov /** 848ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey * Inserts an item in the groups table 849ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey */ 850ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey private long insertGroup(ContentValues values, Account account) { 851ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 852ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 853ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey ContentValues overriddenValues = new ContentValues(values); 854ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (!resolveAccount(overriddenValues, account)) { 855ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return -1; 856ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 857ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 858ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // Replace package with internal mapping 859ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final String packageName = overriddenValues.getAsString(Groups.PACKAGE); 860ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey overriddenValues.put(Groups.PACKAGE_ID, mOpenHelper.getPackageId(packageName)); 861ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey overriddenValues.remove(Groups.PACKAGE); 862ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 863ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return db.insert(Tables.GROUPS, Groups.TITLE, overriddenValues); 864ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 865ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 866ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey /** 8671f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey * Inserts a presence update. 8681f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey */ 8691f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey private long insertPresence(ContentValues values) { 8701f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 8711f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey final String handle = values.getAsString(Presence.IM_HANDLE); 8721f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey final String protocol = values.getAsString(Presence.IM_PROTOCOL); 8731f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (TextUtils.isEmpty(handle) || TextUtils.isEmpty(protocol)) { 8741f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey throw new IllegalArgumentException("IM_PROTOCOL and IM_HANDLE are required"); 8751f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 8761f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 8771f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // TODO: generalize to allow other providers to match against email 8781f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey boolean matchEmail = GTALK_PROTOCOL_STRING.equals(protocol); 8791f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 8801f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String selection; 8811f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String[] selectionArgs; 8821f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (matchEmail) { 8831f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey selection = "(" + Clauses.WHERE_IM_MATCHES + ") OR (" + Clauses.WHERE_EMAIL_MATCHES + ")"; 8841f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey selectionArgs = new String[] { protocol, handle, handle }; 8851f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 8861f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey selection = Clauses.WHERE_IM_MATCHES; 8871f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey selectionArgs = new String[] { protocol, handle }; 8881f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 8891f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 8901f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey long dataId = -1; 8911f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey long aggId = -1; 8921f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey Cursor cursor = null; 8931f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey try { 894ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor = db.query(Tables.DATA_JOIN_MIMETYPES_CONTACTS_PACKAGES_AGGREGATES, 895ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Projections.PROJ_DATA_CONTACTS, selection, selectionArgs, null, null, null); 8961f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey if (cursor.moveToFirst()) { 897ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey dataId = cursor.getLong(Projections.COL_DATA_ID); 898ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey aggId = cursor.getLong(Projections.COL_AGGREGATE_ID); 8991f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } else { 9001f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // No contact found, return a null URI 9011f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return -1; 9021f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 9031f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } finally { 90431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (cursor != null) { 90531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov cursor.close(); 90631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 9071f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 9081f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 9091f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey values.put(Presence.DATA_ID, dataId); 9101f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey values.put(Presence.AGGREGATE_ID, aggId); 9111f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 9121f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey // Insert the presence update 9131f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey long presenceId = db.replace(Tables.PRESENCE, null, values); 9141f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return presenceId; 9151f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 9161f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 9174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 9184f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public int delete(Uri uri, String selection, String[] selectionArgs) { 919508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 920508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey final int match = sUriMatcher.match(uri); 921508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey switch (match) { 92235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 92335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana return mOpenHelper.getSyncState().delete(db, selection, selectionArgs); 92435ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 9256bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov case AGGREGATES_ID: { 9266bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov long aggregateId = ContentUris.parseId(uri); 9276bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 9286bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov // Remove references to the aggregate first 9296bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov ContentValues values = new ContentValues(); 9306bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov values.putNull(Contacts.AGGREGATE_ID); 931b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey db.update(Tables.CONTACTS, values, Contacts.AGGREGATE_ID + "=" + aggregateId, null); 9326bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 933b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey return db.delete(Tables.AGGREGATES, BaseColumns._ID + "=" + aggregateId, null); 9346bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 9356bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 936508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case CONTACTS_ID: { 937508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long contactId = ContentUris.parseId(uri); 938b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey int contactsDeleted = db.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null); 939b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey int dataDeleted = db.delete(Tables.DATA, Data.CONTACT_ID + "=" + contactId, null); 940508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey return contactsDeleted + dataDeleted; 941508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 942508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 943508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: { 944508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 945ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return deleteData(dataId); 946ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 947ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 948ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 949ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 950ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey final long groupMembershipMimetypeId = mOpenHelper 951ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE); 952ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey int groupsDeleted = db.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null); 953ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey int dataDeleted = db.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "=" 954ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "=" 955ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + groupId, null); 956ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey mOpenHelper.updateAllVisible(); 957ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey return groupsDeleted + dataDeleted; 958508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 959508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey 9601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey case PRESENCE: { 9611f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey return db.delete(Tables.PRESENCE, null, null); 9621f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 9631f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 964508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey default: 965508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey throw new UnsupportedOperationException("Unknown uri: " + uri); 966508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey } 9674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 9684f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 969f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana private static Account readAccountFromQueryParams(Uri uri) { 970035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final String name = uri.getQueryParameter(Contacts.ACCOUNT_NAME); 971035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final String type = uri.getQueryParameter(Contacts.ACCOUNT_TYPE); 972f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana if (TextUtils.isEmpty(name) || TextUtils.isEmpty(type)) { 973f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana return null; 974f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana } 975f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana return new Account(name, type); 976f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana } 977f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana 978ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 9794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 9804f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 98100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 98235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana int count = 0; 98300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 98400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar final int match = sUriMatcher.match(uri); 98500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar switch(match) { 98635ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 98735ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana return mOpenHelper.getSyncState().update(db, values, selection, selectionArgs); 98835ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 989c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar // TODO(emillar): We will want to disallow editing the aggregates table at some point. 99000d71133c63c882fb41729ddc3a52f66fb155374Evan Millar case AGGREGATES: { 99100d71133c63c882fb41729ddc3a52f66fb155374Evan Millar count = db.update(Tables.AGGREGATES, values, selection, selectionArgs); 99200d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 99300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 99400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 99500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar case AGGREGATES_ID: { 996d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov count = updateAggregateData(db, ContentUris.parseId(uri), values); 997c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar break; 998c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 999c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 1000c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar case DATA_ID: { 1001c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar boolean containsIsSuperPrimary = values.containsKey(Data.IS_SUPER_PRIMARY); 1002c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar boolean containsIsPrimary = values.containsKey(Data.IS_PRIMARY); 1003c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar final long id = ContentUris.parseId(uri); 1004c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 1005c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar // Remove primary or super primary values being set to 0. This is disallowed by the 1006c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar // content provider. 10078b341f8ea85257c5f7103863405e0273921e16bcEvan Millar if (containsIsSuperPrimary && values.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { 1008c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar containsIsSuperPrimary = false; 1009c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar values.remove(Data.IS_SUPER_PRIMARY); 1010c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 10118b341f8ea85257c5f7103863405e0273921e16bcEvan Millar if (containsIsPrimary && values.getAsInteger(Data.IS_PRIMARY) == 0) { 1012c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar containsIsPrimary = false; 1013c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar values.remove(Data.IS_PRIMARY); 1014c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 1015c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 1016c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar if (containsIsSuperPrimary) { 1017c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar setIsSuperPrimary(id); 1018c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar setIsPrimary(id); 1019c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 1020c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar // Now that we've taken care of setting these, remove them from "values". 1021c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar values.remove(Data.IS_SUPER_PRIMARY); 1022c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar if (containsIsPrimary) { 1023c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar values.remove(Data.IS_PRIMARY); 1024c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 1025c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } else if (containsIsPrimary) { 1026c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar setIsPrimary(id); 1027c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 1028c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar // Now that we've taken care of setting this, remove it from "values". 1029c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar values.remove(Data.IS_PRIMARY); 1030c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 1031c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 1032c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar if (values.size() > 0) { 1033c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar String selectionWithId = (Data._ID + " = " + ContentUris.parseId(uri) + " ") 1034f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana + (selection == null ? "" : " AND " + selection); 1035c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar count = db.update(Tables.DATA, values, selectionWithId, selectionArgs); 1036c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 103700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar break; 103800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 10397e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 10407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana case CONTACTS: { 10417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana count = db.update(Tables.CONTACTS, values, selection, selectionArgs); 10427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 10437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 10447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 10457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana case CONTACTS_ID: { 10467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String selectionWithId = (Contacts._ID + " = " + ContentUris.parseId(uri) + " ") 10477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana + (selection == null ? "" : " AND " + selection); 10487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana count = db.update(Tables.CONTACTS, values, selectionWithId, selectionArgs); 10497e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana Log.i(TAG, "Selection is: " + selectionWithId); 10507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 10517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 10527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 10537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana case DATA: { 10547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana count = db.update(Tables.DATA, values, selection, selectionArgs); 10557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 10567e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 10577e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 1058ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 1059ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey count = db.update(Tables.GROUPS, values, selection, selectionArgs); 1060ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey mOpenHelper.updateAllVisible(); 1061ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1062ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1063ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1064ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 1065ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 1066ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey String selectionWithId = (Groups._ID + "=" + groupId + " ") 1067ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey + (selection == null ? "" : " AND " + selection); 1068ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey count = db.update(Tables.GROUPS, values, selectionWithId, selectionArgs); 1069ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1070ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey // If changing visibility, then update aggregates 1071ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey if (values.containsKey(Groups.GROUP_VISIBLE)) { 1072ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey mOpenHelper.updateAllVisible(); 1073ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1074ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1075ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1076ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1077ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1078127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 1079127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov count = updateAggregationException(db, values); 1080b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 1081b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 1082b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 1083619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey case RESTRICTION_EXCEPTIONS: { 1084619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Enforce required fields 1085619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey boolean hasFields = values.containsKey(RestrictionExceptions.PACKAGE_PROVIDER) 1086619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey && values.containsKey(RestrictionExceptions.PACKAGE_CLIENT) 1087619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey && values.containsKey(RestrictionExceptions.ALLOW_ACCESS); 1088619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (!hasFields) { 1089619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey throw new IllegalArgumentException("PACKAGE_PROVIDER, PACKAGE_CLIENT, and" 1090619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey + "ALLOW_ACCESS are all required fields"); 1091619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1092619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1093619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final String packageProvider = values 1094619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey .getAsString(RestrictionExceptions.PACKAGE_PROVIDER); 1095619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final boolean allowAccess = (values 1096619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey .getAsInteger(RestrictionExceptions.ALLOW_ACCESS) == 1); 1097619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1098619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final Context context = getContext(); 1099619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final PackageManager pm = context.getPackageManager(); 1100619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1101619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Enforce that caller has authority over the requested package 1102619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: move back to Binder.getCallingUid() when we can stub-out test suite 1103619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final int callingUid = OpenHelper 1104619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey .getUidForPackageName(pm, context.getPackageName()); 1105619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final String[] ownedPackages = pm.getPackagesForUid(callingUid); 1106619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (!isContained(ownedPackages, packageProvider)) { 1107619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey throw new RuntimeException( 1108619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey "Requested PACKAGE_PROVIDER doesn't belong to calling UID."); 1109619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1110619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1111619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Add or remove exception using exception helper 1112619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (allowAccess) { 1113619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mOpenHelper.addRestrictionException(context, values); 1114619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } else { 1115619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey mOpenHelper.removeRestrictionException(context, values); 1116619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1117619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1118619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 1119619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1120619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 11217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana default: 11227e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new UnsupportedOperationException("Unknown uri: " + uri); 112300d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 112400d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 112500d71133c63c882fb41729ddc3a52f66fb155374Evan Millar if (count > 0) { 112600d71133c63c882fb41729ddc3a52f66fb155374Evan Millar getContext().getContentResolver().notifyChange(uri, null); 112700d71133c63c882fb41729ddc3a52f66fb155374Evan Millar } 112800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar return count; 11294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 11304f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1131d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov private int updateAggregateData(SQLiteDatabase db, long aggregateId, ContentValues values) { 1132d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1133d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // First update all constituent contacts 1134d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov ContentValues optionValues = new ContentValues(3); 1135d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov if (values.containsKey(Aggregates.CUSTOM_RINGTONE)) { 1136d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov optionValues.put(ContactOptionsColumns.CUSTOM_RINGTONE, 1137d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.getAsString(Aggregates.CUSTOM_RINGTONE)); 1138d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 1139d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov if (values.containsKey(Aggregates.SEND_TO_VOICEMAIL)) { 1140d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov optionValues.put(ContactOptionsColumns.SEND_TO_VOICEMAIL, 1141d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.getAsBoolean(Aggregates.SEND_TO_VOICEMAIL)); 1142d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 1143d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1144d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Nothing to update - just return 1145d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov if (optionValues.size() == 0) { 1146d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return 0; 1147d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 1148d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1149ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Cursor c = db.query(Tables.CONTACTS, Projections.PROJ_CONTACTS, Contacts.AGGREGATE_ID + "=" 1150d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov + aggregateId, null, null, null, null); 1151d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov try { 1152d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov while (c.moveToNext()) { 1153ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long contactId = c.getLong(Projections.COL_CONTACT_ID); 1154d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1155d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov optionValues.put(ContactOptionsColumns._ID, contactId); 1156d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov db.replace(Tables.CONTACT_OPTIONS, null, optionValues); 1157d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 1158d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } finally { 1159d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov c.close(); 1160d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 1161d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1162d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // Now update the aggregate itself. Ignore all supplied fields except rington and 1163d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov // send_to_voicemail 1164d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov optionValues.clear(); 1165d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov if (values.containsKey(Aggregates.CUSTOM_RINGTONE)) { 1166d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov optionValues.put(Aggregates.CUSTOM_RINGTONE, 1167d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.getAsString(Aggregates.CUSTOM_RINGTONE)); 1168d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 1169d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov if (values.containsKey(Aggregates.SEND_TO_VOICEMAIL)) { 1170d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov optionValues.put(Aggregates.SEND_TO_VOICEMAIL, 1171d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov values.getAsBoolean(Aggregates.SEND_TO_VOICEMAIL)); 1172d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 1173d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1174d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return db.update(Tables.AGGREGATES, optionValues, Aggregates._ID + "=" + aggregateId, null); 1175d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 1176d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov 1177127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private static class ContactPair { 1178127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov final long contactId1; 1179127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov final long contactId2; 1180127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 1181127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov /** 1182127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov * Constructor that ensures that this.contactId1 < this.contactId2 1183127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov */ 1184127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov public ContactPair(long contactId1, long contactId2) { 1185127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov if (contactId1 < contactId2) { 1186127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov this.contactId1 = contactId1; 1187127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov this.contactId2 = contactId2; 1188127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } else { 1189127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov this.contactId2 = contactId1; 1190127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov this.contactId1 = contactId2; 1191127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 1192127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 1193127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 119480c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 1195127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov private int updateAggregationException(SQLiteDatabase db, ContentValues values) { 1196127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov int exceptionType = values.getAsInteger(AggregationExceptions.TYPE); 1197127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov long aggregateId = values.getAsInteger(AggregationExceptions.AGGREGATE_ID); 1198127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov long contactId = values.getAsInteger(AggregationExceptions.CONTACT_ID); 119980c457131bd22afe34828d1a5d15e90bb5f43375Dmitri Plotnikov 1200127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // First, we build a list of contactID-contactID pairs for the given aggregate and contact. 1201127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov ArrayList<ContactPair> pairs = new ArrayList<ContactPair>(); 1202ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Cursor c = db.query(Tables.CONTACTS, Projections.PROJ_CONTACTS, 1203127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov Contacts.AGGREGATE_ID + "=" + aggregateId, 1204127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov null, null, null, null); 1205127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov try { 1206127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov while (c.moveToNext()) { 1207ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long aggregatedContactId = c.getLong(Projections.COL_CONTACT_ID); 1208e2e0ba75ce239f0f5481cdef9082daebf8fc2d35Dmitri Plotnikov if (aggregatedContactId != contactId) { 1209e2e0ba75ce239f0f5481cdef9082daebf8fc2d35Dmitri Plotnikov pairs.add(new ContactPair(aggregatedContactId, contactId)); 1210e2e0ba75ce239f0f5481cdef9082daebf8fc2d35Dmitri Plotnikov } 1211b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 1212b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } finally { 1213b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov c.close(); 1214b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 1215127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 1216127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // Now we iterate through all contact pairs to see if we need to insert/delete/update 1217127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // the corresponding exception 1218127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov ContentValues exceptionValues = new ContentValues(3); 1219127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov exceptionValues.put(AggregationExceptions.TYPE, exceptionType); 1220127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov for (ContactPair pair : pairs) { 1221127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov final String whereClause = 1222127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov AggregationExceptionColumns.CONTACT_ID1 + "=" + pair.contactId1 + " AND " 1223127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov + AggregationExceptionColumns.CONTACT_ID2 + "=" + pair.contactId2; 1224127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC) { 1225127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov db.delete(Tables.AGGREGATION_EXCEPTIONS, whereClause, null); 1226127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } else { 1227127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov exceptionValues.put(AggregationExceptionColumns.CONTACT_ID1, pair.contactId1); 1228127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov exceptionValues.put(AggregationExceptionColumns.CONTACT_ID2, pair.contactId2); 1229127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov db.replace(Tables.AGGREGATION_EXCEPTIONS, AggregationExceptions._ID, 1230127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov exceptionValues); 1231127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 1232127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov } 1233127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 1234127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov mContactAggregator.markContactForAggregation(contactId); 1235127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov mContactAggregator.aggregateContact(contactId); 12367a39bf269294a8130ddd463460b9b36cf4ff74a8Dmitri Plotnikov if (exceptionType == AggregationExceptions.TYPE_AUTOMATIC 12377a39bf269294a8130ddd463460b9b36cf4ff74a8Dmitri Plotnikov || exceptionType == AggregationExceptions.TYPE_KEEP_OUT) { 12387a39bf269294a8130ddd463460b9b36cf4ff74a8Dmitri Plotnikov mContactAggregator.updateAggregateData(aggregateId); 12397a39bf269294a8130ddd463460b9b36cf4ff74a8Dmitri Plotnikov } 1240127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov 1241127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // The return value is fake - we just confirm that we made a change, not count actual 1242127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov // rows changed. 1243127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov return 1; 1244b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 1245b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 1246619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 1247619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Test if a {@link String} value appears in the given list. 1248619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 1249619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private boolean isContained(String[] array, String value) { 1250bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar if (array != null) { 1251bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar for (String test : array) { 1252bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar if (value.equals(test)) { 1253bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar return true; 1254bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar } 1255619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1256619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1257619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey return false; 1258619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1259619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1260619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 1261619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Test if a {@link String} value appears in the given list, and add to the 1262619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * array if the value doesn't already appear. 1263619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 1264619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private String[] assertContained(String[] array, String value) { 1265bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar if (array == null) { 1266bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar array = new String[] {value}; 1267bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar } else if (!isContained(array, value)) { 1268619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey String[] newArray = new String[array.length + 1]; 1269619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey System.arraycopy(array, 0, newArray, 0, array.length); 1270619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey newArray[array.length] = value; 1271619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey array = newArray; 1272619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1273619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey return array; 1274619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1275619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 12764f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 12774f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 12784f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton String sortOrder) { 12794f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 128035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 1281d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 12821f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String groupBy = null; 12831f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey String limit = null; 1284bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar String aggregateIdColName = Tables.AGGREGATES + "." + Aggregates._ID; 12854f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1286619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: Consider writing a test case for RestrictionExceptions when you 1287619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // write a new query() block to make sure it protects restricted data. 1288a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 12894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 129035ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana case SYNCSTATE: 129135ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana return mOpenHelper.getSyncState().query(db, projection, selection, selectionArgs, 129235ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana sortOrder); 129335ed95769096bb5dd406ad7d1fcaa49a0e35a307Fred Quintana 12946bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov case AGGREGATES: { 1295b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey qb.setTables(Tables.AGGREGATES); 1296619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyAggregateRestrictionExceptions(qb); 1297619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyAggregatePrimaryRestrictionExceptions(sAggregatesProjectionMap); 1298619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey qb.setProjectionMap(sAggregatesProjectionMap); 1299619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 1300619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1301619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1302619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey case AGGREGATES_ID: { 1303619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey long aggId = ContentUris.parseId(uri); 1304619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey qb.setTables(Tables.AGGREGATES); 1305ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.appendWhere(AggregatesColumns.CONCRETE_ID + "=" + aggId + " AND "); 1306619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyAggregateRestrictionExceptions(qb); 1307619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyAggregatePrimaryRestrictionExceptions(sAggregatesProjectionMap); 13086bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov qb.setProjectionMap(sAggregatesProjectionMap); 13096bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 13106bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 13116bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov 13121f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey case AGGREGATES_SUMMARY: { 1313619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: join into social status tables 13141f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey qb.setTables(Tables.AGGREGATES_JOIN_PRESENCE_PRIMARY_PHONE); 1315619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyAggregateRestrictionExceptions(qb); 1316619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyAggregatePrimaryRestrictionExceptions(sAggregatesSummaryProjectionMap); 1317619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey projection = assertContained(projection, Aggregates.PRIMARY_PHONE_ID); 13181f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey qb.setProjectionMap(sAggregatesSummaryProjectionMap); 1319bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar groupBy = aggregateIdColName; 13201f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 13211f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 13221f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 13231f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey case AGGREGATES_SUMMARY_ID: { 1324619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: join into social status tables 13251f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey long aggId = ContentUris.parseId(uri); 13261f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey qb.setTables(Tables.AGGREGATES_JOIN_PRESENCE_PRIMARY_PHONE); 1327ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.appendWhere(AggregatesColumns.CONCRETE_ID + "=" + aggId + " AND "); 1328619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyAggregateRestrictionExceptions(qb); 1329619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyAggregatePrimaryRestrictionExceptions(sAggregatesSummaryProjectionMap); 1330619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey projection = assertContained(projection, Aggregates.PRIMARY_PHONE_ID); 13311f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey qb.setProjectionMap(sAggregatesSummaryProjectionMap); 1332bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar groupBy = aggregateIdColName; 13331f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey break; 13341f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey } 13351f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey 1336ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case AGGREGATES_SUMMARY_FILTER: { 1337619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: filter query based on callingUid 1338ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.setTables(Tables.AGGREGATES_JOIN_PRESENCE_PRIMARY_PHONE); 1339ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.setProjectionMap(sAggregatesSummaryProjectionMap); 1340ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 1341ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.appendWhere(buildAggregateLookupWhereClause(uri.getLastPathSegment())); 1342ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 1343bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar groupBy = aggregateIdColName; 1344ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 1345ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 1346ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 1347d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar case AGGREGATES_SUMMARY_STREQUENT_FILTER: 1348d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar case AGGREGATES_SUMMARY_STREQUENT: { 1349d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the first query for starred 1350d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb.setTables(Tables.AGGREGATES_JOIN_PRESENCE_PRIMARY_PHONE); 1351d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb.setProjectionMap(sAggregatesSummaryProjectionMap); 1352d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar if (match == AGGREGATES_SUMMARY_STREQUENT_FILTER 1353d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 1354d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb.appendWhere(buildAggregateLookupWhereClause(uri.getLastPathSegment())); 1355d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 1356d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String starredQuery = qb.buildQuery(projection, Aggregates.STARRED + "=1", 1357bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar null, aggregateIdColName, null, null, 1358d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar null /* limit */); 1359d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 1360d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Build the second query for frequent 1361d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb = new SQLiteQueryBuilder(); 1362d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb.setTables(Tables.AGGREGATES_JOIN_PRESENCE_PRIMARY_PHONE); 1363d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb.setProjectionMap(sAggregatesSummaryProjectionMap); 1364d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar if (match == AGGREGATES_SUMMARY_STREQUENT_FILTER 1365d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar && uri.getPathSegments().size() > 3) { 1366d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar qb.appendWhere(buildAggregateLookupWhereClause(uri.getLastPathSegment())); 1367d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 1368d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String frequentQuery = qb.buildQuery(projection, 1369d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar Aggregates.TIMES_CONTACTED + " > 0 AND (" + Aggregates.STARRED 1370d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar + " = 0 OR " + Aggregates.STARRED + " IS NULL)", 1371bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar null, aggregateIdColName, null, null, null); 1372d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 1373d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar // Put them together 1374d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar final String query = qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, 1375d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar STREQUENT_ORDER_BY, STREQUENT_LIMIT); 1376d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar Cursor c = db.rawQueryWithFactory(null, query, null, 1377d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar Tables.AGGREGATES_JOIN_PRESENCE_PRIMARY_PHONE); 1378d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 1379d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar if ((c != null) && !isTemporary()) { 1380d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar c.setNotificationUri(getContext().getContentResolver(), 1381d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar ContactsContract.AUTHORITY_URI); 1382d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 1383d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar return c; 1384d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar } 1385d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar 1386b67163a1088f09c59f324350662eb18772fac6b6Evan Millar case AGGREGATES_SUMMARY_GROUP: { 1387b67163a1088f09c59f324350662eb18772fac6b6Evan Millar qb.setTables(Tables.AGGREGATES_JOIN_PRESENCE_PRIMARY_PHONE); 1388b67163a1088f09c59f324350662eb18772fac6b6Evan Millar applyAggregateRestrictionExceptions(qb); 1389b67163a1088f09c59f324350662eb18772fac6b6Evan Millar applyAggregatePrimaryRestrictionExceptions(sAggregatesSummaryProjectionMap); 1390b67163a1088f09c59f324350662eb18772fac6b6Evan Millar projection = assertContained(projection, Aggregates.PRIMARY_PHONE_ID); 1391b67163a1088f09c59f324350662eb18772fac6b6Evan Millar qb.setProjectionMap(sAggregatesSummaryProjectionMap); 1392b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (uri.getPathSegments().size() > 2) { 1393b67163a1088f09c59f324350662eb18772fac6b6Evan Millar qb.appendWhere(" AND " + sAggregatesInGroupSelect); 1394b67163a1088f09c59f324350662eb18772fac6b6Evan Millar selectionArgs = appendGroupArg(selectionArgs, uri.getLastPathSegment()); 1395b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 1396b67163a1088f09c59f324350662eb18772fac6b6Evan Millar groupBy = aggregateIdColName; 1397b67163a1088f09c59f324350662eb18772fac6b6Evan Millar break; 1398b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 1399b67163a1088f09c59f324350662eb18772fac6b6Evan Millar 14006bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov case AGGREGATES_DATA: { 1401619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey long aggId = Long.parseLong(uri.getPathSegments().get(1)); 1402ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.DATA_JOIN_MIMETYPES_CONTACTS_PACKAGES_AGGREGATES); 1403de4c4d84028c6c6999c6d9277b54b661f207b992Evan Millar qb.setProjectionMap(sDataContactsAggregateProjectionMap); 1404619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey qb.appendWhere(Contacts.AGGREGATE_ID + "=" + aggId + " AND "); 1405619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyDataRestrictionExceptions(qb); 14066bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov break; 14076bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov } 140800d71133c63c882fb41729ddc3a52f66fb155374Evan Millar 1409ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES_FILTER: { 1410ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.DATA_JOIN_MIMETYPES_CONTACTS_PACKAGES_AGGREGATES); 1411ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.setProjectionMap(sDataContactsAggregateProjectionMap); 1412ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.appendWhere(Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE + "'"); 1413ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar if (uri.getPathSegments().size() > 2) { 1414ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.appendWhere(" AND " + buildAggregateLookupWhereClause( 1415ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar uri.getLastPathSegment())); 1416ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 1417ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 1418ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 1419ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1420ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case PHONES: { 1421ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.DATA_JOIN_MIMETYPES_CONTACTS_PACKAGES_AGGREGATES); 1422ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.setProjectionMap(sDataContactsAggregateProjectionMap); 1423ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.appendWhere(Data.MIMETYPE + " = \"" + Phone.CONTENT_ITEM_TYPE + "\""); 1424ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 1425ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 1426ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 1427ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar case POSTALS: { 1428ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.DATA_JOIN_MIMETYPES_CONTACTS_PACKAGES_AGGREGATES); 1429ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.setProjectionMap(sDataContactsAggregateProjectionMap); 1430ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar qb.appendWhere(Data.MIMETYPE + " = \"" + Postal.CONTENT_ITEM_TYPE + "\""); 1431ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar break; 1432ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 1433ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 14344f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case CONTACTS: { 1435035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana qb.setTables(Tables.CONTACTS_JOIN_PACKAGES); 14364f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton qb.setProjectionMap(sContactsProjectionMap); 1437619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyContactsRestrictionExceptions(qb); 14384f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 14394f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 14404f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 14414f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case CONTACTS_ID: { 1442619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey long contactId = ContentUris.parseId(uri); 1443035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana qb.setTables(Tables.CONTACTS_JOIN_PACKAGES); 14444f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton qb.setProjectionMap(sContactsProjectionMap); 1445ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.appendWhere(ContactsColumns.CONCRETE_ID + "=" + contactId + " AND "); 1446619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyContactsRestrictionExceptions(qb); 14474f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 14484f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 14494f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1450a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case CONTACTS_DATA: { 1451619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey long contactId = Long.parseLong(uri.getPathSegments().get(1)); 1452ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.DATA_JOIN_MIMETYPES_CONTACTS_PACKAGES); 14537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana qb.setProjectionMap(sDataContactsProjectionMap); 1454619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey qb.appendWhere(Data.CONTACT_ID + "=" + contactId + " AND "); 1455619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyDataRestrictionExceptions(qb); 1456a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1457a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1458a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 145928ab0f857caa92402878244d9c5ea2a59e070935Jeff Sharkey case CONTACTS_FILTER_EMAIL: { 1460619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: filter query based on callingUid 1461ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.DATA_JOIN_MIMETYPES_CONTACTS_PACKAGES_AGGREGATES); 1462e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey qb.setProjectionMap(sDataContactsProjectionMap); 14635d0f923eb4c5351ebf323cc6f19c82acff98693eJeff Sharkey qb.appendWhere(Data.MIMETYPE + "='" + CommonDataKinds.Email.CONTENT_ITEM_TYPE + "'"); 1464e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey qb.appendWhere(" AND " + CommonDataKinds.Email.DATA + "="); 1465e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey qb.appendWhereEscapeString(uri.getPathSegments().get(2)); 1466e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 1467e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 1468e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 1469e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey case DATA: { 1470035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final String accountName = uri.getQueryParameter(Contacts.ACCOUNT_NAME); 1471035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final String accountType = uri.getQueryParameter(Contacts.ACCOUNT_TYPE); 1472343c56b5679c58bf1835a0e219fff57beae6ecefFred Quintana if (!TextUtils.isEmpty(accountName)) { 1473035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana qb.appendWhere(Contacts.ACCOUNT_NAME + "=" 1474035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 1475035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + Contacts.ACCOUNT_TYPE + "=" 1476035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountType) + " AND "); 1477343c56b5679c58bf1835a0e219fff57beae6ecefFred Quintana } 1478ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.DATA_JOIN_MIMETYPES_CONTACTS_PACKAGES); 1479e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey qb.setProjectionMap(sDataProjectionMap); 1480619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyDataRestrictionExceptions(qb); 1481e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey break; 1482e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey } 1483e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey 14844f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case DATA_ID: { 1485ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.DATA_JOIN_MIMETYPES_CONTACTS_PACKAGES); 14864f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton qb.setProjectionMap(sDataProjectionMap); 1487ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.appendWhere(DataColumns.CONCRETE_ID + "=" + ContentUris.parseId(uri) + " AND "); 1488619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyDataRestrictionExceptions(qb); 14894f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton break; 14904f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 14914f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 1492a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton case PHONE_LOOKUP: { 1493619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: filter query based on callingUid 1494a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton if (TextUtils.isEmpty(sortOrder)) { 1495a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // Default the sort order to something reasonable so we get consistent 1496a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton // results when callers don't request an ordering 1497e17c303827c5be8107dcd4a8b64333f349b688f5Jeff Sharkey sortOrder = Data.CONTACT_ID; 1498a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1499a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1500a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final String number = uri.getLastPathSegment(); 1501bf659107617a6291ba8bfeebc3f2e50138075ab5Dmitri Plotnikov OpenHelper.buildPhoneLookupQuery(qb, number); 1502a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton qb.setProjectionMap(sDataContactsProjectionMap); 1503a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton break; 1504a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton } 1505a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton 1506ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS: { 1507ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.GROUPS_JOIN_PACKAGES); 1508ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 1509ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1510ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1511ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1512ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_ID: { 1513ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey long groupId = ContentUris.parseId(uri); 1514ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.GROUPS_JOIN_PACKAGES); 1515ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsProjectionMap); 1516ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.appendWhere(GroupsColumns.CONCRETE_ID + "=" + groupId); 1517ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1518ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1519ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1520ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey case GROUPS_SUMMARY: { 1521ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.GROUPS_JOIN_PACKAGES_DATA_CONTACTS_AGGREGATES); 1522ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setProjectionMap(sGroupsSummaryProjectionMap); 1523ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey groupBy = GroupsColumns.CONCRETE_ID; 1524ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey break; 1525ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey } 1526ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey 1527b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: { 1528127071b6305023a79b7d8f473ef6887843389f6eDmitri Plotnikov qb.setTables(Tables.AGGREGATION_EXCEPTIONS_JOIN_CONTACTS); 1529b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov qb.setProjectionMap(sAggregationExceptionsProjectionMap); 1530b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov break; 1531b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov } 1532b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov 153331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: { 153431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov long aggregateId = Long.parseLong(uri.getPathSegments().get(1)); 153531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final String maxSuggestionsParam = 153631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov uri.getQueryParameter(AggregationSuggestions.MAX_SUGGESTIONS); 153731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 153831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov final int maxSuggestions; 153931b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov if (maxSuggestionsParam != null) { 154031b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = Integer.parseInt(maxSuggestionsParam); 154131b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } else { 154231b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov maxSuggestions = DEFAULT_MAX_SUGGESTIONS; 154331b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 154431b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 154531b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov return mContactAggregator.queryAggregationSuggestions(aggregateId, projection, 154631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov sAggregatesProjectionMap, maxSuggestions); 154731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov } 154831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov 1549619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey case RESTRICTION_EXCEPTIONS: { 1550619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey qb.setTables(Tables.RESTRICTION_EXCEPTIONS); 1551619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey qb.setProjectionMap(sRestrictionExceptionsProjectionMap); 1552619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey break; 1553619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1554619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 15554f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton default: 15564f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton throw new UnsupportedOperationException("Unknown uri: " + uri); 15574f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 15584f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 15594f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton // Perform the query and set the notification uri 15601f42f1958113b2dadc6cf26b51192b42f883f3b0Jeff Sharkey final Cursor c = qb.query(db, projection, selection, selectionArgs, 1561bc5c799a52b5bde2f273efd118ebe2228c3d8f15Evan Millar groupBy, null, sortOrder, limit); 15624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton if (c != null) { 15634f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 15644f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 15654f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton return c; 15664f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 15674f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton 15687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana /** 1569619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Restrict selection of {@link Aggregates} to only public ones, or those 1570619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * the caller has been granted a {@link RestrictionExceptions} to. 1571619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 1572619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private void applyAggregateRestrictionExceptions(SQLiteQueryBuilder qb) { 1573619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final int clientUid = OpenHelper.getUidForPackageName(getContext().getPackageManager(), 1574619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey getContext().getPackageName()); 1575619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1576619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey qb.appendWhere("(" + AggregatesColumns.SINGLE_RESTRICTED_PACKAGE_ID + " IS NULL"); 1577619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final String exceptionClause = mOpenHelper.getRestrictionExceptionClause(clientUid, 1578619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey AggregatesColumns.SINGLE_RESTRICTED_PACKAGE_ID); 1579619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (exceptionClause != null) { 1580619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey qb.appendWhere(" OR (" + exceptionClause + ")"); 1581619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1582619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey qb.appendWhere(")"); 1583619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1584619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1585619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 1586619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Find any exceptions that have been granted to the calling process, and 1587619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * add projections to correctly select {@link Aggregates#PRIMARY_PHONE_ID} 1588619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * and {@link Aggregates#PRIMARY_EMAIL_ID}. 1589619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 1590619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private void applyAggregatePrimaryRestrictionExceptions(HashMap<String, String> projection) { 1591619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: move back to Binder.getCallingUid() when we can stub-out test suite 1592619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final int clientUid = OpenHelper.getUidForPackageName(getContext().getPackageManager(), 1593619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey getContext().getPackageName()); 1594619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1595619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final String projectionPhone = "(CASE WHEN " 1596619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey + mOpenHelper.getRestrictionExceptionClause(clientUid, 1597619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey AggregatesColumns.OPTIMAL_PRIMARY_PHONE_PACKAGE_ID) + " THEN " 1598619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey + AggregatesColumns.OPTIMAL_PRIMARY_PHONE_ID + " ELSE " 1599619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey + AggregatesColumns.FALLBACK_PRIMARY_PHONE_ID + " END) AS " 1600619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey + Aggregates.PRIMARY_PHONE_ID; 1601619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey projection.remove(Aggregates.PRIMARY_PHONE_ID); 1602619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey projection.put(Aggregates.PRIMARY_PHONE_ID, projectionPhone); 1603619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1604619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final String projectionEmail = "(CASE WHEN " 1605619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey + mOpenHelper.getRestrictionExceptionClause(clientUid, 1606619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey AggregatesColumns.OPTIMAL_PRIMARY_EMAIL_PACKAGE_ID) + " THEN " 1607619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey + AggregatesColumns.OPTIMAL_PRIMARY_EMAIL_ID + " ELSE " 1608619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey + AggregatesColumns.FALLBACK_PRIMARY_EMAIL_ID + " END) AS " 1609619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey + Aggregates.PRIMARY_EMAIL_ID; 1610619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey projection.remove(Aggregates.PRIMARY_EMAIL_ID); 1611619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey projection.put(Aggregates.PRIMARY_EMAIL_ID, projectionEmail); 1612619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1613619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1614619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 1615619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Find any exceptions that have been granted to the 1616619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * {@link Binder#getCallingUid()}, and add a limiting clause to the given 1617619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * {@link SQLiteQueryBuilder} to hide restricted data. 1618619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 1619619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private void applyContactsRestrictionExceptions(SQLiteQueryBuilder qb) { 1620619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // TODO: move back to Binder.getCallingUid() when we can stub-out test suite 1621619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final int clientUid = OpenHelper.getUidForPackageName(getContext().getPackageManager(), 1622619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey getContext().getPackageName()); 1623619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1624619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey qb.appendWhere("(" + Contacts.IS_RESTRICTED + "=0"); 1625619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final String exceptionClause = mOpenHelper.getRestrictionExceptionClause(clientUid, 1626619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey ContactsColumns.PACKAGE_ID); 1627619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (exceptionClause != null) { 1628619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey qb.appendWhere(" OR (" + exceptionClause + ")"); 1629619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1630619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey qb.appendWhere(")"); 1631619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1632619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1633619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 1634619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * Find any exceptions that have been granted to the 1635619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * {@link Binder#getCallingUid()}, and add a limiting clause to the given 1636619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey * {@link SQLiteQueryBuilder} to hide restricted data. 1637619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey */ 1638619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey private void applyDataRestrictionExceptions(SQLiteQueryBuilder qb) { 1639619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey applyContactsRestrictionExceptions(qb); 1640619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1641619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1642619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey /** 16437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * An implementation of EntityIterator that joins the contacts and data tables 16447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana * and consumes all the data rows for a contact in order to build the Entity for a contact. 16457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana */ 16467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static class ContactsEntityIterator implements EntityIterator { 16477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private final Cursor mEntityCursor; 16487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private volatile boolean mIsClosed; 16497e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 16507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] DATA_KEYS = new String[]{ 16517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data1", 16527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data2", 16537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data3", 16547e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data4", 16557e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data5", 16567e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data6", 16577e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data7", 16587e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data8", 16597e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data9", 16607e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana "data10"}; 16617e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 16627e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana private static final String[] PROJECTION = new String[]{ 1663035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.ACCOUNT_NAME, 1664035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.ACCOUNT_TYPE, 1665035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.SOURCE_ID, 1666035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.VERSION, 1667035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.DIRTY, 1668035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.Data._ID, 1669035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.Data.MIMETYPE, 1670035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.Data.DATA1, 1671035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.Data.DATA2, 1672035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.Data.DATA3, 1673035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.Data.DATA4, 1674035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.Data.DATA5, 1675035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.Data.DATA6, 1676035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.Data.DATA7, 1677035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.Data.DATA8, 1678035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.Data.DATA9, 1679035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.Data.DATA10, 1680035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.Data.CONTACT_ID, 1681035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.Data.IS_PRIMARY, 1682035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana Contacts.Data.DATA_VERSION}; 1683035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana 1684035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_NAME = 0; 1685035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_ACCOUNT_TYPE = 1; 1686035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_SOURCE_ID = 2; 1687035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_VERSION = 3; 1688035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DIRTY = 4; 1689035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DATA_ID = 5; 1690035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_MIMETYPE = 6; 1691035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DATA1 = 7; 1692035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_CONTACT_ID = 17; 1693035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_IS_PRIMARY = 18; 1694035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana private static final int COLUMN_DATA_VERSION = 19; 16957e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 16967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public ContactsEntityIterator(ContactsProvider2 provider, String contactsIdString, Uri uri, 16977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String selection, String[] selectionArgs, String sortOrder) { 16987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = false; 16997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final String updatedSortOrder = (sortOrder == null) 17017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ? Contacts.Data.CONTACT_ID 17027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana : (Contacts.Data.CONTACT_ID + "," + sortOrder); 17037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteDatabase db = provider.mOpenHelper.getReadableDatabase(); 17057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 1706ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey qb.setTables(Tables.DATA_JOIN_MIMETYPES_CONTACTS_PACKAGES); 1707035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana qb.setProjectionMap(sDataContactsProjectionMap); 17087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (contactsIdString != null) { 17097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana qb.appendWhere(Data.CONTACT_ID + "=" + contactsIdString); 17107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 1711035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final String accountName = uri.getQueryParameter(Contacts.ACCOUNT_NAME); 1712035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana final String accountType = uri.getQueryParameter(Contacts.ACCOUNT_TYPE); 1713035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana if (!TextUtils.isEmpty(accountName)) { 1714035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana qb.appendWhere(Contacts.ACCOUNT_NAME + "=" 1715035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountName) + " AND " 1716035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + Contacts.ACCOUNT_TYPE + "=" 1717035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana + DatabaseUtils.sqlEscapeString(accountType)); 1718035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana } 17197e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor = qb.query(db, PROJECTION, selection, selectionArgs, 17207e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana null, null, updatedSortOrder); 17217e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.moveToFirst(); 17227e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17237e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17247e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public void close() { 17257e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 17267e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("closing when already closed"); 17277e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17287e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mIsClosed = true; 17297e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana mEntityCursor.close(); 17307e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17317e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public boolean hasNext() throws RemoteException { 17337e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 17347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling hasNext() when the iterator is closed"); 17357e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17367e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17377e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return !mEntityCursor.isAfterLast(); 17387e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17397e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public Entity next() throws RemoteException { 17417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (mIsClosed) { 17427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("calling next() when the iterator is closed"); 17437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (!hasNext()) { 17457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new IllegalStateException("you may only call next() if hasNext() is true"); 17467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17477e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17487e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteCursor c = (SQLiteCursor) mEntityCursor; 17497e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17507e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final long contactId = c.getLong(COLUMN_CONTACT_ID); 17517e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17527e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // we expect the cursor is already at the row we need to read from 17537e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues contactValues = new ContentValues(); 1754035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana contactValues.put(Contacts.ACCOUNT_NAME, c.getString(COLUMN_ACCOUNT_NAME)); 1755035b4cc204be2641079a0b04e9ee9791a8f8248bFred Quintana contactValues.put(Contacts.ACCOUNT_TYPE, c.getString(COLUMN_ACCOUNT_TYPE)); 17567e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contactValues.put(Contacts._ID, contactId); 17577e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contactValues.put(Contacts.DIRTY, c.getLong(COLUMN_DIRTY)); 1758f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana contactValues.put(Contacts.VERSION, c.getLong(COLUMN_VERSION)); 17597e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contactValues.put(Contacts.SOURCE_ID, c.getString(COLUMN_SOURCE_ID)); 17607e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana Entity contact = new Entity(contactValues); 17617e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17627e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // read data rows until the contact id changes 17637e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana do { 17647e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (contactId != c.getLong(COLUMN_CONTACT_ID)) { 17657e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana break; 17667e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17677e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // add the data to to the contact 17687e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentValues dataValues = new ContentValues(); 17697e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(Contacts.Data._ID, c.getString(COLUMN_DATA_ID)); 1770f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana dataValues.put(Contacts.Data.MIMETYPE, c.getString(COLUMN_MIMETYPE)); 1771f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana dataValues.put(Contacts.Data.IS_PRIMARY, c.getString(COLUMN_IS_PRIMARY)); 1772f5b20724819e51b339ff6ba5b8eb6b444cc31452Fred Quintana dataValues.put(Contacts.Data.DATA_VERSION, c.getLong(COLUMN_DATA_VERSION)); 17737e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana for (int i = 0; i < 10; i++) { 17747e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int columnIndex = i + COLUMN_DATA1; 17757e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String key = DATA_KEYS[i]; 17767e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (c.isNull(columnIndex)) { 17777e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana // don't put anything 17787e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isLong(columnIndex)) { 17797e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getLong(columnIndex)); 17807e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isFloat(columnIndex)) { 17817e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getFloat(columnIndex)); 17827e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isString(columnIndex)) { 17837e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getString(columnIndex)); 17847e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } else if (c.isBlob(columnIndex)) { 17857e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana dataValues.put(key, c.getBlob(columnIndex)); 17867e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17877e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17887e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contact.addSubValue(Data.CONTENT_URI, dataValues); 17897e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } while (mEntityCursor.moveToNext()); 17907e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 17917e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return contact; 17927e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17937e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 17947e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 1795a8dc456684a104c7e5547ba17d44f952022cd8c5Dmitri Plotnikov @Override 17967e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs, 17977e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String sortOrder) { 17987e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final int match = sUriMatcher.match(uri); 17997e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana switch (match) { 18007e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana case CONTACTS: 18017e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana case CONTACTS_ID: 18027e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana String contactsIdString = null; 18037e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana if (match == CONTACTS_ID) { 18047e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana contactsIdString = uri.getPathSegments().get(1); 18057e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 18067e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 18077e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return new ContactsEntityIterator(this, contactsIdString, 18087e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana uri, selection, selectionArgs, sortOrder); 18097e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana default: 18107e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throw new UnsupportedOperationException("Unknown uri: " + uri); 18117e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 18127e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 18137e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 18144f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton @Override 18154f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton public String getType(Uri uri) { 1816a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton final int match = sUriMatcher.match(uri); 18174f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton switch (match) { 18186bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov case AGGREGATES: return Aggregates.CONTENT_TYPE; 18196bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov case AGGREGATES_ID: return Aggregates.CONTENT_ITEM_TYPE; 18204f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case CONTACTS: return Contacts.CONTENT_TYPE; 18214f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton case CONTACTS_ID: return Contacts.CONTENT_ITEM_TYPE; 1822508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey case DATA_ID: 18236bc8c0d15f4eacd2e92e9064c88cdf0659524a0eDmitri Plotnikov final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 1824508f57ee336c20583400b48b614bd3d57ca849ecJeff Sharkey long dataId = ContentUris.parseId(uri); 1825b650982af7aeb2800efdcea587b8ce153259cf1cJeff Sharkey return mOpenHelper.getDataMimeType(dataId); 182631b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_EXCEPTIONS: return AggregationExceptions.CONTENT_TYPE; 182731b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_EXCEPTION_ID: return AggregationExceptions.CONTENT_ITEM_TYPE; 182831b86315536573a72dc7fff1baac3b314e5a04c3Dmitri Plotnikov case AGGREGATION_SUGGESTIONS: return Aggregates.CONTENT_TYPE; 18294f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 1830a36c566037b4bb05f035d0c2cfd8b51386d7a8a6Jeff Hamilton throw new UnsupportedOperationException("Unknown uri: " + uri); 18314f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton } 18327e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 1833b174c7ccd337a7bea6269139c9b09acc69ae40c1Dmitri Plotnikov @Override 18347e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 18357e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana throws OperationApplicationException { 18367e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana 18377e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 18387e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana db.beginTransaction(); 18397e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana try { 18407e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana ContentProviderResult[] results = super.applyBatch(operations); 18417e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana db.setTransactionSuccessful(); 18427e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana return results; 18437e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } finally { 18447e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana db.endTransaction(); 18457e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 18467e4676dfcaa8853b81c2133e0e318ed3436fe787Fred Quintana } 1847c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 1848c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 1849c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to primary, and resets all data records of 1850c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * the same mimetype and under the same contact to not be primary. 1851c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 1852c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 1853c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 1854c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private void setIsPrimary(long dataId) { 1855c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(1, dataId); 1856c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(2, dataId); 1857c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.bindLong(3, dataId); 1858c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetPrimaryStatement.execute(); 1859c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 1860c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar 1861c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar /* 1862c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * Sets the given dataId record in the "data" table to "super primary", and resets all data 1863c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * records of the same mimetype and under the same aggregate to not be "super primary". 1864c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * 1865c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar * @param dataId the id of the data record to be set to primary. 1866c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar */ 1867c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar private void setIsSuperPrimary(long dataId) { 1868c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(1, dataId); 1869c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(2, dataId); 1870c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.bindLong(3, dataId); 1871c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar mSetSuperPrimaryStatement.execute(); 1872619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1873619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Find the parent aggregate and package for this new primary 1874619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 1875619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1876619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey long aggId = -1; 1877619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey long packageId = -1; 1878619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey boolean isRestricted = false; 1879619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey String mimeType = null; 1880619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1881619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey Cursor cursor = null; 1882619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey try { 1883ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey cursor = db.query(Tables.DATA_JOIN_MIMETYPES_CONTACTS_PACKAGES, 1884ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey Projections.PROJ_DATA_CONTACTS, DataColumns.CONCRETE_ID + "=" + dataId, null, 1885ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey null, null, null); 1886619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (cursor.moveToFirst()) { 1887ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey aggId = cursor.getLong(Projections.COL_AGGREGATE_ID); 1888ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey packageId = cursor.getLong(Projections.COL_PACKAGE_ID); 1889ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey isRestricted = (cursor.getInt(Projections.COL_IS_RESTRICTED) == 1); 1890ca8172420c0913dff96ea607d477d8b8abfe5ddbJeff Sharkey mimeType = cursor.getString(Projections.COL_MIMETYPE); 1891619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1892619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } finally { 1893619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (cursor != null) { 1894619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey cursor.close(); 1895619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1896619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1897619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1898619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Bypass aggregate update if no parent found, or if we don't keep track 1899619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // of super-primary for this mimetype. 1900d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov if (aggId == -1) { 1901d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov return; 1902d35d9c748af4c3182679c4c546137acfc11eb7a8Dmitri Plotnikov } 1903619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1904619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey boolean isPhone = CommonDataKinds.Phone.CONTENT_ITEM_TYPE.equals(mimeType); 1905619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey boolean isEmail = CommonDataKinds.Email.CONTENT_ITEM_TYPE.equals(mimeType); 1906619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1907619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Record this value as the new primary for the parent aggregate 1908619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey final ContentValues values = new ContentValues(); 1909619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (isPhone) { 1910619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey values.put(AggregatesColumns.OPTIMAL_PRIMARY_PHONE_ID, dataId); 1911619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey values.put(AggregatesColumns.OPTIMAL_PRIMARY_PHONE_PACKAGE_ID, packageId); 1912619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } else if (isEmail) { 1913619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey values.put(AggregatesColumns.OPTIMAL_PRIMARY_EMAIL_ID, dataId); 1914619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey values.put(AggregatesColumns.OPTIMAL_PRIMARY_EMAIL_PACKAGE_ID, packageId); 1915619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1916619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1917619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // If this data is unrestricted, then also set as fallback 1918619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (!isRestricted && isPhone) { 1919619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey values.put(AggregatesColumns.FALLBACK_PRIMARY_PHONE_ID, dataId); 1920619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } else if (!isRestricted && isEmail) { 1921619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey values.put(AggregatesColumns.FALLBACK_PRIMARY_EMAIL_ID, dataId); 1922619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1923619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1924619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey // Push update into aggregates table, if needed 1925619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey if (values.size() > 0) { 1926619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey db.update(Tables.AGGREGATES, values, Aggregates._ID + "=" + aggId, null); 1927619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey } 1928619871b0fb0175d75ff9336bfe5aec0b27b9bdadJeff Sharkey 1929c0834a81ef469e6ee7e72ce34a8a02855a162858Evan Millar } 1930ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 1931ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar private String buildAggregateLookupWhereClause(String filterParam) { 1932ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar StringBuilder filter = new StringBuilder(); 1933ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append(Tables.AGGREGATES); 1934ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append("."); 1935ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append(Aggregates._ID); 1936ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append(" IN (SELECT "); 1937ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append(Contacts.AGGREGATE_ID); 1938ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append(" FROM "); 1939ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append(Tables.CONTACTS); 1940ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append(" WHERE "); 1941ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar filter.append(Contacts._ID); 1942d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar filter.append(" IN (SELECT contact_id FROM name_lookup WHERE normalized_name GLOB '"); 1943ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar // NOTE: Query parameters won't work here since the SQL compiler 1944ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar // needs to parse the actual string to know that it can use the 1945ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar // index to do a prefix scan. 1946d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar filter.append(NameNormalizer.normalize(filterParam) + "*"); 1947d3b76e00699679c519adc1c1770cd28ee6ae7aa3Evan Millar filter.append("'))"); 1948ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar return filter.toString(); 1949ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar } 1950ea0ec7120315589eaafb45d88ff872abbde35e38Evan Millar 1951b67163a1088f09c59f324350662eb18772fac6b6Evan Millar private String[] appendGroupArg(String[] selectionArgs, String arg) { 1952b67163a1088f09c59f324350662eb18772fac6b6Evan Millar if (selectionArgs == null) { 1953b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return new String[] {arg}; 1954b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } else { 1955b67163a1088f09c59f324350662eb18772fac6b6Evan Millar int newLength = selectionArgs.length + 1; 1956b67163a1088f09c59f324350662eb18772fac6b6Evan Millar String[] newSelectionArgs = new String[newLength]; 1957b67163a1088f09c59f324350662eb18772fac6b6Evan Millar System.arraycopy(selectionArgs, 0, newSelectionArgs, 0, selectionArgs.length); 1958b67163a1088f09c59f324350662eb18772fac6b6Evan Millar newSelectionArgs[newLength - 1] = arg; 1959b67163a1088f09c59f324350662eb18772fac6b6Evan Millar return newSelectionArgs; 1960b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 1961b67163a1088f09c59f324350662eb18772fac6b6Evan Millar } 19624f864360c24bd26c111bf38a035e8e2d2609e84aJeff Hamilton} 1963