LegacyApiSupport.java revision 0126458fabecb6514bf6d368ae6a066a78856a91
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16package com.android.providers.contacts; 17 18import com.android.providers.contacts.OpenHelper.DataColumns; 19import com.android.providers.contacts.OpenHelper.ExtensionsColumns; 20import com.android.providers.contacts.OpenHelper.GroupsColumns; 21import com.android.providers.contacts.OpenHelper.MimetypesColumns; 22import com.android.providers.contacts.OpenHelper.PhoneColumns; 23import com.android.providers.contacts.OpenHelper.PresenceColumns; 24import com.android.providers.contacts.OpenHelper.RawContactsColumns; 25import com.android.providers.contacts.OpenHelper.Tables; 26 27import android.accounts.Account; 28import android.app.SearchManager; 29import android.content.ContentUris; 30import android.content.ContentValues; 31import android.content.Context; 32import android.content.UriMatcher; 33import android.database.Cursor; 34import android.database.DatabaseUtils; 35import android.database.sqlite.SQLiteDatabase; 36import android.database.sqlite.SQLiteQueryBuilder; 37import android.database.sqlite.SQLiteStatement; 38import android.net.Uri; 39import android.provider.ContactsContract; 40import android.provider.Contacts.ContactMethods; 41import android.provider.Contacts.People; 42import android.provider.ContactsContract.Data; 43import android.provider.ContactsContract.Groups; 44import android.provider.ContactsContract.Presence; 45import android.provider.ContactsContract.RawContacts; 46import android.provider.ContactsContract.CommonDataKinds.Email; 47import android.provider.ContactsContract.CommonDataKinds.GroupMembership; 48import android.provider.ContactsContract.CommonDataKinds.Im; 49import android.provider.ContactsContract.CommonDataKinds.Note; 50import android.provider.ContactsContract.CommonDataKinds.Organization; 51import android.provider.ContactsContract.CommonDataKinds.Phone; 52import android.provider.ContactsContract.CommonDataKinds.Photo; 53import android.provider.ContactsContract.CommonDataKinds.StructuredName; 54import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 55 56import java.util.HashMap; 57 58public class LegacyApiSupport implements OpenHelper.Delegate { 59 60 private static final String TAG = "ContactsProviderV1"; 61 62 private static final String NON_EXISTENT_ACCOUNT_TYPE = "android.INVALID_ACCOUNT_TYPE"; 63 private static final String NON_EXISTENT_ACCOUNT_NAME = "invalid"; 64 65 private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 66 67 private static final int PEOPLE = 1; 68 private static final int PEOPLE_ID = 2; 69 private static final int PEOPLE_UPDATE_CONTACT_TIME = 3; 70 private static final int ORGANIZATIONS = 4; 71 private static final int ORGANIZATIONS_ID = 5; 72 private static final int PEOPLE_CONTACTMETHODS = 6; 73 private static final int PEOPLE_CONTACTMETHODS_ID = 7; 74 private static final int CONTACTMETHODS = 8; 75 private static final int CONTACTMETHODS_ID = 9; 76 private static final int PEOPLE_PHONES = 10; 77 private static final int PEOPLE_PHONES_ID = 11; 78 private static final int PHONES = 12; 79 private static final int PHONES_ID = 13; 80 private static final int EXTENSIONS = 14; 81 private static final int EXTENSIONS_ID = 15; 82 private static final int PEOPLE_EXTENSIONS = 16; 83 private static final int PEOPLE_EXTENSIONS_ID = 17; 84 private static final int GROUPS = 18; 85 private static final int GROUPS_ID = 19; 86 private static final int GROUPMEMBERSHIP = 20; 87 private static final int GROUPMEMBERSHIP_ID = 21; 88 private static final int PEOPLE_GROUPMEMBERSHIP = 22; 89 private static final int PEOPLE_GROUPMEMBERSHIP_ID = 23; 90 private static final int PEOPLE_PHOTO = 24; 91 private static final int PHOTOS = 25; 92 private static final int PHOTOS_ID = 26; 93 private static final int PEOPLE_FILTER = 29; 94 private static final int DELETED_PEOPLE = 30; 95 private static final int DELETED_GROUPS = 31; 96 private static final int SEARCH_SUGGESTIONS = 32; 97 private static final int PHONES_FILTER = 33; 98 99 private static final String PEOPLE_JOINS = 100 " LEFT OUTER JOIN data name ON (raw_contacts._id = name.raw_contact_id" 101 + " AND (SELECT mimetype FROM mimetypes WHERE mimetypes._id = name.mimetype_id)" 102 + "='" + StructuredName.CONTENT_ITEM_TYPE + "')" 103 + " LEFT OUTER JOIN data organization ON (raw_contacts._id = organization.raw_contact_id" 104 + " AND (SELECT mimetype FROM mimetypes WHERE mimetypes._id = organization.mimetype_id)" 105 + "='" + Organization.CONTENT_ITEM_TYPE + "' AND organization.is_primary)" 106 + " LEFT OUTER JOIN data email ON (raw_contacts._id = email.raw_contact_id" 107 + " AND (SELECT mimetype FROM mimetypes WHERE mimetypes._id = email.mimetype_id)" 108 + "='" + Email.CONTENT_ITEM_TYPE + "' AND email.is_primary)" 109 + " LEFT OUTER JOIN data note ON (raw_contacts._id = note.raw_contact_id" 110 + " AND (SELECT mimetype FROM mimetypes WHERE mimetypes._id = note.mimetype_id)" 111 + "='" + Note.CONTENT_ITEM_TYPE + "')" 112 + " LEFT OUTER JOIN data phone ON (raw_contacts._id = phone.raw_contact_id" 113 + " AND (SELECT mimetype FROM mimetypes WHERE mimetypes._id = phone.mimetype_id)" 114 + "='" + Phone.CONTENT_ITEM_TYPE + "' AND phone.is_primary)"; 115 116 public static final String DATA_JOINS = 117 " JOIN mimetypes ON (mimetypes._id = data.mimetype_id)" 118 + " JOIN raw_contacts ON (raw_contacts._id = data.raw_contact_id)" 119 + PEOPLE_JOINS; 120 121 public static final String PRESENCE_JOINS = 122 " LEFT OUTER JOIN presence ON (" 123 + " presence.presence_id = (SELECT max(presence_id) FROM presence" 124 + " WHERE view_v1_people._id = presence_raw_contact_id))"; 125 126 private static final String PHONETIC_NAME_SQL = "trim(trim(" 127 + "ifnull(name." + StructuredName.PHONETIC_GIVEN_NAME + ",' ')||' '||" 128 + "ifnull(name." + StructuredName.PHONETIC_MIDDLE_NAME + ",' '))||' '||" 129 + "ifnull(name." + StructuredName.PHONETIC_FAMILY_NAME + ",' ')) "; 130 131 private static final String CONTACT_METHOD_KIND_SQL = 132 "CAST ((CASE WHEN mimetype='" + Email.CONTENT_ITEM_TYPE + "'" 133 + " THEN " + android.provider.Contacts.KIND_EMAIL 134 + " ELSE" 135 + " (CASE WHEN mimetype='" + Im.CONTENT_ITEM_TYPE +"'" 136 + " THEN " + android.provider.Contacts.KIND_IM 137 + " ELSE" 138 + " (CASE WHEN mimetype='" + StructuredPostal.CONTENT_ITEM_TYPE + "'" 139 + " THEN " + android.provider.Contacts.KIND_POSTAL 140 + " ELSE" 141 + " NULL" 142 + " END)" 143 + " END)" 144 + " END) AS INTEGER)"; 145 146 public interface LegacyTables { 147 public static final String PEOPLE = "view_v1_people"; 148 public static final String PEOPLE_JOIN_PRESENCE = "view_v1_people" + PRESENCE_JOINS; 149 public static final String GROUPS = "view_v1_groups"; 150 public static final String ORGANIZATIONS = "view_v1_organizations"; 151 public static final String CONTACT_METHODS = "view_v1_contact_methods"; 152 public static final String PHONES = "view_v1_phones"; 153 public static final String EXTENSIONS = "view_v1_extensions"; 154 public static final String GROUP_MEMBERSHIP = "view_v1_group_membership"; 155 public static final String PHOTOS = "view_v1_photos"; 156 public static final String PRESENCE_JOIN_CONTACTS = Tables.PRESENCE + 157 " LEFT OUTER JOIN " + Tables.RAW_CONTACTS 158 + " ON (" + Tables.PRESENCE + "." + PresenceColumns.RAW_CONTACT_ID + "=" 159 + RawContactsColumns.CONCRETE_ID + ")"; 160 } 161 162 private static final String[] ORGANIZATION_MIME_TYPES = new String[] { 163 Organization.CONTENT_ITEM_TYPE 164 }; 165 166 private static final String[] CONTACT_METHOD_MIME_TYPES = new String[] { 167 Email.CONTENT_ITEM_TYPE, 168 Im.CONTENT_ITEM_TYPE, 169 StructuredPostal.CONTENT_ITEM_TYPE, 170 }; 171 172 private static final String[] PHONE_MIME_TYPES = new String[] { 173 Phone.CONTENT_ITEM_TYPE 174 }; 175 176 private interface PhotoQuery { 177 String[] COLUMNS = { Data._ID }; 178 179 int _ID = 0; 180 } 181 182 /** 183 * A custom data row that is used to store legacy photo data fields no 184 * longer directly supported by the API. 185 */ 186 private interface LegacyPhotoData { 187 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo_v1_extras"; 188 189 public static final String PHOTO_DATA_ID = Data.DATA1; 190 public static final String LOCAL_VERSION = Data.DATA2; 191 public static final String DOWNLOAD_REQUIRED = Data.DATA3; 192 public static final String EXISTS_ON_SERVER = Data.DATA4; 193 public static final String SYNC_ERROR = Data.DATA5; 194 } 195 196 public static final String LEGACY_PHOTO_JOIN = 197 " LEFT OUTER JOIN data legacy_photo ON (raw_contacts._id = legacy_photo.raw_contact_id" 198 + " AND (SELECT mimetype FROM mimetypes WHERE mimetypes._id = legacy_photo.mimetype_id)" 199 + "='" + LegacyPhotoData.CONTENT_ITEM_TYPE + "'" 200 + " AND " + DataColumns.CONCRETE_ID + " = legacy_photo." + LegacyPhotoData.PHOTO_DATA_ID 201 + ")"; 202 203 private static final HashMap<String, String> sPeopleProjectionMap; 204 private static final HashMap<String, String> sOrganizationProjectionMap; 205 private static final HashMap<String, String> sContactMethodProjectionMap; 206 private static final HashMap<String, String> sPhoneProjectionMap; 207 private static final HashMap<String, String> sExtensionProjectionMap; 208 private static final HashMap<String, String> sGroupProjectionMap; 209 private static final HashMap<String, String> sGroupMembershipProjectionMap; 210 private static final HashMap<String, String> sPhotoProjectionMap; 211 212 static { 213 214 // Contacts URI matching table 215 UriMatcher matcher = sUriMatcher; 216 217 String authority = android.provider.Contacts.AUTHORITY; 218 matcher.addURI(authority, "extensions", EXTENSIONS); 219 matcher.addURI(authority, "extensions/#", EXTENSIONS_ID); 220 matcher.addURI(authority, "groups", GROUPS); 221 matcher.addURI(authority, "groups/#", GROUPS_ID); 222// matcher.addURI(authority, "groups/name/*/members", GROUP_NAME_MEMBERS); 223// matcher.addURI(authority, "groups/name/*/members/filter/*", 224// GROUP_NAME_MEMBERS_FILTER); 225// matcher.addURI(authority, "groups/system_id/*/members", GROUP_SYSTEM_ID_MEMBERS); 226// matcher.addURI(authority, "groups/system_id/*/members/filter/*", 227// GROUP_SYSTEM_ID_MEMBERS_FILTER); 228 matcher.addURI(authority, "groupmembership", GROUPMEMBERSHIP); 229 matcher.addURI(authority, "groupmembership/#", GROUPMEMBERSHIP_ID); 230// matcher.addURI(authority, "groupmembershipraw", GROUPMEMBERSHIP_RAW); 231 matcher.addURI(authority, "people", PEOPLE); 232// matcher.addURI(authority, "people/strequent", PEOPLE_STREQUENT); 233// matcher.addURI(authority, "people/strequent/filter/*", PEOPLE_STREQUENT_FILTER); 234 matcher.addURI(authority, "people/filter/*", PEOPLE_FILTER); 235// matcher.addURI(authority, "people/with_phones_filter/*", 236// PEOPLE_WITH_PHONES_FILTER); 237// matcher.addURI(authority, "people/with_email_or_im_filter/*", 238// PEOPLE_WITH_EMAIL_OR_IM_FILTER); 239 matcher.addURI(authority, "people/#", PEOPLE_ID); 240 matcher.addURI(authority, "people/#/extensions", PEOPLE_EXTENSIONS); 241 matcher.addURI(authority, "people/#/extensions/#", PEOPLE_EXTENSIONS_ID); 242 matcher.addURI(authority, "people/#/phones", PEOPLE_PHONES); 243 matcher.addURI(authority, "people/#/phones/#", PEOPLE_PHONES_ID); 244// matcher.addURI(authority, "people/#/phones_with_presence", 245// PEOPLE_PHONES_WITH_PRESENCE); 246 matcher.addURI(authority, "people/#/photo", PEOPLE_PHOTO); 247// matcher.addURI(authority, "people/#/photo/data", PEOPLE_PHOTO_DATA); 248 matcher.addURI(authority, "people/#/contact_methods", PEOPLE_CONTACTMETHODS); 249// matcher.addURI(authority, "people/#/contact_methods_with_presence", 250// PEOPLE_CONTACTMETHODS_WITH_PRESENCE); 251 matcher.addURI(authority, "people/#/contact_methods/#", PEOPLE_CONTACTMETHODS_ID); 252// matcher.addURI(authority, "people/#/organizations", PEOPLE_ORGANIZATIONS); 253// matcher.addURI(authority, "people/#/organizations/#", PEOPLE_ORGANIZATIONS_ID); 254 matcher.addURI(authority, "people/#/groupmembership", PEOPLE_GROUPMEMBERSHIP); 255 matcher.addURI(authority, "people/#/groupmembership/#", PEOPLE_GROUPMEMBERSHIP_ID); 256// matcher.addURI(authority, "people/raw", PEOPLE_RAW); 257// matcher.addURI(authority, "people/owner", PEOPLE_OWNER); 258 matcher.addURI(authority, "people/#/update_contact_time", 259 PEOPLE_UPDATE_CONTACT_TIME); 260 matcher.addURI(authority, "deleted_people", DELETED_PEOPLE); 261 matcher.addURI(authority, "deleted_groups", DELETED_GROUPS); 262 matcher.addURI(authority, "phones", PHONES); 263// matcher.addURI(authority, "phones_with_presence", PHONES_WITH_PRESENCE); 264 matcher.addURI(authority, "phones/filter/*", PHONES_FILTER); 265// matcher.addURI(authority, "phones/filter_name/*", PHONES_FILTER_NAME); 266// matcher.addURI(authority, "phones/mobile_filter_name/*", 267// PHONES_MOBILE_FILTER_NAME); 268 matcher.addURI(authority, "phones/#", PHONES_ID); 269 matcher.addURI(authority, "photos", PHOTOS); 270 matcher.addURI(authority, "photos/#", PHOTOS_ID); 271 matcher.addURI(authority, "contact_methods", CONTACTMETHODS); 272// matcher.addURI(authority, "contact_methods/email", CONTACTMETHODS_EMAIL); 273// matcher.addURI(authority, "contact_methods/email/*", CONTACTMETHODS_EMAIL_FILTER); 274 matcher.addURI(authority, "contact_methods/#", CONTACTMETHODS_ID); 275// matcher.addURI(authority, "contact_methods/with_presence", 276// CONTACTMETHODS_WITH_PRESENCE); 277 matcher.addURI(authority, "organizations", ORGANIZATIONS); 278 matcher.addURI(authority, "organizations/#", ORGANIZATIONS_ID); 279// matcher.addURI(authority, "voice_dialer_timestamp", VOICE_DIALER_TIMESTAMP); 280 matcher.addURI(authority, SearchManager.SUGGEST_URI_PATH_QUERY, 281 SEARCH_SUGGESTIONS); 282 matcher.addURI(authority, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", 283 SEARCH_SUGGESTIONS); 284// matcher.addURI(authority, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/#", 285// SEARCH_SHORTCUT); 286// matcher.addURI(authority, "settings", SETTINGS); 287// 288// matcher.addURI(authority, "live_folders/people", LIVE_FOLDERS_PEOPLE); 289// matcher.addURI(authority, "live_folders/people/*", 290// LIVE_FOLDERS_PEOPLE_GROUP_NAME); 291// matcher.addURI(authority, "live_folders/people_with_phones", 292// LIVE_FOLDERS_PEOPLE_WITH_PHONES); 293// matcher.addURI(authority, "live_folders/favorites", 294// LIVE_FOLDERS_PEOPLE_FAVORITES); 295 296 297 HashMap<String, String> peopleProjectionMap = new HashMap<String, String>(); 298 peopleProjectionMap.put(People.NAME, People.NAME); 299 peopleProjectionMap.put(People.DISPLAY_NAME, People.DISPLAY_NAME); 300 peopleProjectionMap.put(People.PHONETIC_NAME, People.PHONETIC_NAME); 301 peopleProjectionMap.put(People.NOTES, People.NOTES); 302 peopleProjectionMap.put(People.TIMES_CONTACTED, People.TIMES_CONTACTED); 303 peopleProjectionMap.put(People.LAST_TIME_CONTACTED, People.LAST_TIME_CONTACTED); 304 peopleProjectionMap.put(People.CUSTOM_RINGTONE, People.CUSTOM_RINGTONE); 305 peopleProjectionMap.put(People.SEND_TO_VOICEMAIL, People.SEND_TO_VOICEMAIL); 306 peopleProjectionMap.put(People.STARRED, People.STARRED); 307 308 String IM_PROTOCOL_SQL = 309 "(CASE WHEN " + Presence.PROTOCOL + "=" + Im.PROTOCOL_CUSTOM 310 + " THEN 'custom:'||" + Presence.CUSTOM_PROTOCOL 311 + " ELSE 'pre:'||" + Presence.PROTOCOL 312 + " END)"; 313 314 sPeopleProjectionMap = new HashMap<String, String>(peopleProjectionMap); 315 sPeopleProjectionMap.put(People._ID, People._ID); 316 sPeopleProjectionMap.put(People.PRIMARY_ORGANIZATION_ID, People.PRIMARY_ORGANIZATION_ID); 317 sPeopleProjectionMap.put(People.PRIMARY_EMAIL_ID, People.PRIMARY_EMAIL_ID); 318 sPeopleProjectionMap.put(People.PRIMARY_PHONE_ID, People.PRIMARY_PHONE_ID); 319 sPeopleProjectionMap.put(People.NUMBER, People.NUMBER); 320 sPeopleProjectionMap.put(People.TYPE, People.TYPE); 321 sPeopleProjectionMap.put(People.LABEL, People.LABEL); 322 sPeopleProjectionMap.put(People.NUMBER_KEY, People.NUMBER_KEY); 323 sPeopleProjectionMap.put(People.IM_PROTOCOL, IM_PROTOCOL_SQL + " AS " + People.IM_PROTOCOL); 324 sPeopleProjectionMap.put(People.IM_HANDLE, People.IM_HANDLE); 325 sPeopleProjectionMap.put(People.IM_ACCOUNT, People.IM_ACCOUNT); 326 sPeopleProjectionMap.put(People.PRESENCE_STATUS, People.PRESENCE_STATUS); 327 sPeopleProjectionMap.put(People.PRESENCE_CUSTOM_STATUS, People.PRESENCE_CUSTOM_STATUS); 328 329 sOrganizationProjectionMap = new HashMap<String, String>(); 330 sOrganizationProjectionMap.put(android.provider.Contacts.Organizations._ID, 331 android.provider.Contacts.Organizations._ID); 332 sOrganizationProjectionMap.put(android.provider.Contacts.Organizations.PERSON_ID, 333 android.provider.Contacts.Organizations.PERSON_ID); 334 sOrganizationProjectionMap.put(android.provider.Contacts.Organizations.ISPRIMARY, 335 android.provider.Contacts.Organizations.ISPRIMARY); 336 sOrganizationProjectionMap.put(android.provider.Contacts.Organizations.COMPANY, 337 android.provider.Contacts.Organizations.COMPANY); 338 sOrganizationProjectionMap.put(android.provider.Contacts.Organizations.TYPE, 339 android.provider.Contacts.Organizations.TYPE); 340 sOrganizationProjectionMap.put(android.provider.Contacts.Organizations.LABEL, 341 android.provider.Contacts.Organizations.LABEL); 342 sOrganizationProjectionMap.put(android.provider.Contacts.Organizations.TITLE, 343 android.provider.Contacts.Organizations.TITLE); 344 345 sContactMethodProjectionMap = new HashMap<String, String>(peopleProjectionMap); 346 sContactMethodProjectionMap.put(ContactMethods._ID, ContactMethods._ID); 347 sContactMethodProjectionMap.put(ContactMethods.PERSON_ID, ContactMethods.PERSON_ID); 348 sContactMethodProjectionMap.put(ContactMethods.KIND, ContactMethods.KIND); 349 sContactMethodProjectionMap.put(ContactMethods.ISPRIMARY, ContactMethods.ISPRIMARY); 350 sContactMethodProjectionMap.put(ContactMethods.TYPE, ContactMethods.TYPE); 351 sContactMethodProjectionMap.put(ContactMethods.DATA, ContactMethods.DATA); 352 sContactMethodProjectionMap.put(ContactMethods.LABEL, ContactMethods.LABEL); 353 sContactMethodProjectionMap.put(ContactMethods.AUX_DATA, ContactMethods.AUX_DATA); 354 355 sPhoneProjectionMap = new HashMap<String, String>(peopleProjectionMap); 356 sPhoneProjectionMap.put(android.provider.Contacts.Phones._ID, 357 android.provider.Contacts.Phones._ID); 358 sPhoneProjectionMap.put(android.provider.Contacts.Phones.PERSON_ID, 359 android.provider.Contacts.Phones.PERSON_ID); 360 sPhoneProjectionMap.put(android.provider.Contacts.Phones.ISPRIMARY, 361 android.provider.Contacts.Phones.ISPRIMARY); 362 sPhoneProjectionMap.put(android.provider.Contacts.Phones.NUMBER, 363 android.provider.Contacts.Phones.NUMBER); 364 sPhoneProjectionMap.put(android.provider.Contacts.Phones.TYPE, 365 android.provider.Contacts.Phones.TYPE); 366 sPhoneProjectionMap.put(android.provider.Contacts.Phones.LABEL, 367 android.provider.Contacts.Phones.LABEL); 368 sPhoneProjectionMap.put(android.provider.Contacts.Phones.NUMBER_KEY, 369 android.provider.Contacts.Phones.NUMBER_KEY); 370 371 sExtensionProjectionMap = new HashMap<String, String>(); 372 sExtensionProjectionMap.put(android.provider.Contacts.Extensions._ID, 373 android.provider.Contacts.Extensions._ID); 374 sExtensionProjectionMap.put(android.provider.Contacts.Extensions.PERSON_ID, 375 android.provider.Contacts.Extensions.PERSON_ID); 376 sExtensionProjectionMap.put(android.provider.Contacts.Extensions.NAME, 377 android.provider.Contacts.Extensions.NAME); 378 sExtensionProjectionMap.put(android.provider.Contacts.Extensions.VALUE, 379 android.provider.Contacts.Extensions.VALUE); 380 381 sGroupProjectionMap = new HashMap<String, String>(); 382 sGroupProjectionMap.put(android.provider.Contacts.Groups._ID, 383 android.provider.Contacts.Groups._ID); 384 sGroupProjectionMap.put(android.provider.Contacts.Groups.NAME, 385 android.provider.Contacts.Groups.NAME); 386 sGroupProjectionMap.put(android.provider.Contacts.Groups.NOTES, 387 android.provider.Contacts.Groups.NOTES); 388 sGroupProjectionMap.put(android.provider.Contacts.Groups.SYSTEM_ID, 389 android.provider.Contacts.Groups.SYSTEM_ID); 390 391 sGroupMembershipProjectionMap = new HashMap<String, String>(); 392 sGroupMembershipProjectionMap.put(android.provider.Contacts.GroupMembership._ID, 393 android.provider.Contacts.GroupMembership._ID); 394 sGroupMembershipProjectionMap.put(android.provider.Contacts.GroupMembership.PERSON_ID, 395 android.provider.Contacts.GroupMembership.PERSON_ID); 396 sGroupMembershipProjectionMap.put(android.provider.Contacts.GroupMembership.GROUP_ID, 397 android.provider.Contacts.GroupMembership.GROUP_ID); 398 399 sPhotoProjectionMap = new HashMap<String, String>(); 400 sPhotoProjectionMap.put(android.provider.Contacts.Photos._ID, 401 android.provider.Contacts.Photos._ID); 402 sPhotoProjectionMap.put(android.provider.Contacts.Photos.PERSON_ID, 403 android.provider.Contacts.Photos.PERSON_ID); 404 sPhotoProjectionMap.put(android.provider.Contacts.Photos.DATA, 405 android.provider.Contacts.Photos.DATA); 406 sPhotoProjectionMap.put(android.provider.Contacts.Photos.LOCAL_VERSION, 407 android.provider.Contacts.Photos.LOCAL_VERSION); 408 sPhotoProjectionMap.put(android.provider.Contacts.Photos.DOWNLOAD_REQUIRED, 409 android.provider.Contacts.Photos.DOWNLOAD_REQUIRED); 410 sPhotoProjectionMap.put(android.provider.Contacts.Photos.EXISTS_ON_SERVER, 411 android.provider.Contacts.Photos.EXISTS_ON_SERVER); 412 sPhotoProjectionMap.put(android.provider.Contacts.Photos.SYNC_ERROR, 413 android.provider.Contacts.Photos.SYNC_ERROR); 414 } 415 416 private final Context mContext; 417 private final OpenHelper mOpenHelper; 418 private final ContactsProvider2 mContactsProvider; 419 private final NameSplitter mPhoneticNameSplitter; 420 private final GlobalSearchSupport mGlobalSearchSupport; 421 422 /** Precompiled sql statement for incrementing times contacted for a contact */ 423 private final SQLiteStatement mLastTimeContactedUpdate; 424 425 private final ContentValues mValues = new ContentValues(); 426 private Account mAccount; 427 428 public LegacyApiSupport(Context context, OpenHelper openHelper, 429 ContactsProvider2 contactsProvider, GlobalSearchSupport globalSearchSupport) { 430 mContext = context; 431 mContactsProvider = contactsProvider; 432 mOpenHelper = openHelper; 433 mGlobalSearchSupport = globalSearchSupport; 434 mOpenHelper.setDelegate(this); 435 436 mPhoneticNameSplitter = new NameSplitter("", "", "", 437 context.getString(com.android.internal.R.string.common_name_conjunctions)); 438 439 SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 440 mLastTimeContactedUpdate = db.compileStatement("UPDATE " + Tables.RAW_CONTACTS + " SET " 441 + RawContacts.TIMES_CONTACTED + "=" 442 + RawContacts.TIMES_CONTACTED + "+1," 443 + RawContacts.LAST_TIME_CONTACTED + "=? WHERE " 444 + RawContacts._ID + "=?"); 445 } 446 447 private void ensureDefaultAccount() { 448 if (mAccount == null) { 449 mAccount = mContactsProvider.getDefaultAccount(); 450 if (mAccount == null) { 451 452 // This fall-through account will not match any data in the database, which 453 // is the expected behavior 454 mAccount = new Account(NON_EXISTENT_ACCOUNT_NAME, NON_EXISTENT_ACCOUNT_TYPE); 455 } 456 } 457 } 458 459 public void createDatabase(SQLiteDatabase db) { 460 461 db.execSQL("DROP VIEW IF EXISTS " + LegacyTables.PEOPLE + ";"); 462 db.execSQL("CREATE VIEW " + LegacyTables.PEOPLE + " AS SELECT " + 463 RawContactsColumns.CONCRETE_ID 464 + " AS " + android.provider.Contacts.People._ID + ", " + 465 "name." + StructuredName.DISPLAY_NAME 466 + " AS " + People.NAME + ", " + 467 Tables.RAW_CONTACTS + "." + RawContactsColumns.DISPLAY_NAME 468 + " AS " + People.DISPLAY_NAME + ", " + 469 PHONETIC_NAME_SQL 470 + " AS " + People.PHONETIC_NAME + " , " + 471 "note." + Note.NOTE 472 + " AS " + People.NOTES + ", " + 473 RawContacts.ACCOUNT_NAME + ", " + 474 RawContacts.ACCOUNT_TYPE + ", " + 475 Tables.RAW_CONTACTS + "." + RawContacts.TIMES_CONTACTED 476 + " AS " + People.TIMES_CONTACTED + ", " + 477 Tables.RAW_CONTACTS + "." + RawContacts.LAST_TIME_CONTACTED 478 + " AS " + People.LAST_TIME_CONTACTED + ", " + 479 Tables.RAW_CONTACTS + "." + RawContacts.CUSTOM_RINGTONE 480 + " AS " + People.CUSTOM_RINGTONE + ", " + 481 Tables.RAW_CONTACTS + "." + RawContacts.SEND_TO_VOICEMAIL 482 + " AS " + People.SEND_TO_VOICEMAIL + ", " + 483 Tables.RAW_CONTACTS + "." + RawContacts.STARRED 484 + " AS " + People.STARRED + ", " + 485 "organization." + Data._ID 486 + " AS " + People.PRIMARY_ORGANIZATION_ID + ", " + 487 "email." + Data._ID 488 + " AS " + People.PRIMARY_EMAIL_ID + ", " + 489 "phone." + Data._ID 490 + " AS " + People.PRIMARY_PHONE_ID + ", " + 491 "phone." + Phone.NUMBER 492 + " AS " + People.NUMBER + ", " + 493 "phone." + Phone.TYPE 494 + " AS " + People.TYPE + ", " + 495 "phone." + Phone.LABEL 496 + " AS " + People.LABEL + ", " + 497 "phone." + PhoneColumns.NORMALIZED_NUMBER 498 + " AS " + People.NUMBER_KEY + 499 " FROM " + Tables.RAW_CONTACTS + PEOPLE_JOINS + 500 " WHERE " + Tables.RAW_CONTACTS + "." + RawContacts.DELETED + "=0" 501 + " AND " + RawContacts.IS_RESTRICTED + "=0" + 502 ";"); 503 504 db.execSQL("DROP VIEW IF EXISTS " + LegacyTables.ORGANIZATIONS + ";"); 505 db.execSQL("CREATE VIEW " + LegacyTables.ORGANIZATIONS + " AS SELECT " + 506 DataColumns.CONCRETE_ID 507 + " AS " + android.provider.Contacts.Organizations._ID + ", " + 508 Data.RAW_CONTACT_ID 509 + " AS " + android.provider.Contacts.Organizations.PERSON_ID + ", " + 510 Data.IS_PRIMARY 511 + " AS " + android.provider.Contacts.Organizations.ISPRIMARY + ", " + 512 RawContacts.ACCOUNT_NAME + ", " + 513 RawContacts.ACCOUNT_TYPE + ", " + 514 Organization.COMPANY 515 + " AS " + android.provider.Contacts.Organizations.COMPANY + ", " + 516 Organization.TYPE 517 + " AS " + android.provider.Contacts.Organizations.TYPE + ", " + 518 Organization.LABEL 519 + " AS " + android.provider.Contacts.Organizations.LABEL + ", " + 520 Organization.TITLE 521 + " AS " + android.provider.Contacts.Organizations.TITLE + 522 " FROM " + Tables.DATA_JOIN_MIMETYPE_RAW_CONTACTS + 523 " WHERE " + MimetypesColumns.CONCRETE_MIMETYPE + "='" 524 + Organization.CONTENT_ITEM_TYPE + "'" 525 + " AND " + Tables.RAW_CONTACTS + "." + RawContacts.DELETED + "=0" 526 + " AND " + RawContacts.IS_RESTRICTED + "=0" + 527 ";"); 528 529 String DATA_SQL = "(CASE WHEN " + Data.MIMETYPE + "='" + Im.CONTENT_ITEM_TYPE + "'" 530 + " THEN (CASE WHEN " + Tables.DATA + "." + Im.PROTOCOL + "=" + Im.PROTOCOL_CUSTOM 531 + " THEN 'custom:'||" + Tables.DATA + "." + Im.CUSTOM_PROTOCOL 532 + " ELSE 'pre:'||" + Tables.DATA + "." + Im.PROTOCOL 533 + " END)" 534 + " ELSE " + DataColumns.CONCRETE_DATA2 535 + " END)"; 536 537 db.execSQL("DROP VIEW IF EXISTS " + LegacyTables.CONTACT_METHODS + ";"); 538 db.execSQL("CREATE VIEW " + LegacyTables.CONTACT_METHODS + " AS SELECT " + 539 DataColumns.CONCRETE_ID 540 + " AS " + ContactMethods._ID + ", " + 541 DataColumns.CONCRETE_RAW_CONTACT_ID 542 + " AS " + ContactMethods.PERSON_ID + ", " + 543 CONTACT_METHOD_KIND_SQL 544 + " AS " + ContactMethods.KIND + ", " + 545 DataColumns.CONCRETE_IS_PRIMARY 546 + " AS " + ContactMethods.ISPRIMARY + ", " + 547 DataColumns.CONCRETE_DATA1 548 + " AS " + ContactMethods.TYPE + ", " + 549 DATA_SQL 550 + " AS " + ContactMethods.DATA + ", " + 551 DataColumns.CONCRETE_DATA3 552 + " AS " + ContactMethods.LABEL + ", " + 553 DataColumns.CONCRETE_DATA14 554 + " AS " + ContactMethods.AUX_DATA + ", " + 555 "name." + StructuredName.DISPLAY_NAME 556 + " AS " + ContactMethods.NAME + ", " + 557 Tables.RAW_CONTACTS + "." + RawContactsColumns.DISPLAY_NAME 558 + " AS " + ContactMethods.DISPLAY_NAME + ", " + 559 RawContacts.ACCOUNT_NAME + ", " + 560 RawContacts.ACCOUNT_TYPE + ", " + 561 PHONETIC_NAME_SQL 562 + " AS " + ContactMethods.PHONETIC_NAME + " , " + 563 "note." + Note.NOTE 564 + " AS " + ContactMethods.NOTES + ", " + 565 Tables.RAW_CONTACTS + "." + RawContacts.TIMES_CONTACTED 566 + " AS " + ContactMethods.TIMES_CONTACTED + ", " + 567 Tables.RAW_CONTACTS + "." + RawContacts.LAST_TIME_CONTACTED 568 + " AS " + ContactMethods.LAST_TIME_CONTACTED + ", " + 569 Tables.RAW_CONTACTS + "." + RawContacts.CUSTOM_RINGTONE 570 + " AS " + ContactMethods.CUSTOM_RINGTONE + ", " + 571 Tables.RAW_CONTACTS + "." + RawContacts.SEND_TO_VOICEMAIL 572 + " AS " + ContactMethods.SEND_TO_VOICEMAIL + ", " + 573 Tables.RAW_CONTACTS + "." + RawContacts.STARRED 574 + " AS " + ContactMethods.STARRED + 575 " FROM " + Tables.DATA + DATA_JOINS + 576 " WHERE " + ContactMethods.KIND + " IS NOT NULL" 577 + " AND " + Tables.RAW_CONTACTS + "." + RawContacts.DELETED + "=0" 578 + " AND " + RawContacts.IS_RESTRICTED + "=0" + 579 ";"); 580 581 582 db.execSQL("DROP VIEW IF EXISTS " + LegacyTables.PHONES + ";"); 583 db.execSQL("CREATE VIEW " + LegacyTables.PHONES + " AS SELECT " + 584 DataColumns.CONCRETE_ID 585 + " AS " + android.provider.Contacts.Phones._ID + ", " + 586 DataColumns.CONCRETE_RAW_CONTACT_ID 587 + " AS " + android.provider.Contacts.Phones.PERSON_ID + ", " + 588 DataColumns.CONCRETE_IS_PRIMARY 589 + " AS " + android.provider.Contacts.Phones.ISPRIMARY + ", " + 590 Tables.DATA + "." + Phone.NUMBER 591 + " AS " + android.provider.Contacts.Phones.NUMBER + ", " + 592 Tables.DATA + "." + Phone.TYPE 593 + " AS " + android.provider.Contacts.Phones.TYPE + ", " + 594 Tables.DATA + "." + Phone.LABEL 595 + " AS " + android.provider.Contacts.Phones.LABEL + ", " + 596 PhoneColumns.CONCRETE_NORMALIZED_NUMBER 597 + " AS " + android.provider.Contacts.Phones.NUMBER_KEY + ", " + 598 "name." + StructuredName.DISPLAY_NAME 599 + " AS " + android.provider.Contacts.Phones.NAME + ", " + 600 Tables.RAW_CONTACTS + "." + RawContactsColumns.DISPLAY_NAME 601 + " AS " + android.provider.Contacts.Phones.DISPLAY_NAME + ", " + 602 RawContacts.ACCOUNT_NAME + ", " + 603 RawContacts.ACCOUNT_TYPE + ", " + 604 PHONETIC_NAME_SQL 605 + " AS " + android.provider.Contacts.Phones.PHONETIC_NAME + " , " + 606 "note." + Note.NOTE 607 + " AS " + android.provider.Contacts.Phones.NOTES + ", " + 608 Tables.RAW_CONTACTS + "." + RawContacts.TIMES_CONTACTED 609 + " AS " + android.provider.Contacts.Phones.TIMES_CONTACTED + ", " + 610 Tables.RAW_CONTACTS + "." + RawContacts.LAST_TIME_CONTACTED 611 + " AS " + android.provider.Contacts.Phones.LAST_TIME_CONTACTED + ", " + 612 Tables.RAW_CONTACTS + "." + RawContacts.CUSTOM_RINGTONE 613 + " AS " + android.provider.Contacts.Phones.CUSTOM_RINGTONE + ", " + 614 Tables.RAW_CONTACTS + "." + RawContacts.SEND_TO_VOICEMAIL 615 + " AS " + android.provider.Contacts.Phones.SEND_TO_VOICEMAIL + ", " + 616 Tables.RAW_CONTACTS + "." + RawContacts.STARRED 617 + " AS " + android.provider.Contacts.Phones.STARRED + 618 " FROM " + Tables.DATA + DATA_JOINS + 619 " WHERE " + MimetypesColumns.CONCRETE_MIMETYPE + "='" 620 + Phone.CONTENT_ITEM_TYPE + "'" 621 + " AND " + Tables.RAW_CONTACTS + "." + RawContacts.DELETED + "=0" 622 + " AND " + RawContacts.IS_RESTRICTED + "=0" + 623 ";"); 624 625 db.execSQL("DROP VIEW IF EXISTS " + LegacyTables.EXTENSIONS + ";"); 626 db.execSQL("CREATE VIEW " + LegacyTables.EXTENSIONS + " AS SELECT " + 627 DataColumns.CONCRETE_ID 628 + " AS " + android.provider.Contacts.Extensions._ID + ", " + 629 DataColumns.CONCRETE_RAW_CONTACT_ID 630 + " AS " + android.provider.Contacts.Extensions.PERSON_ID + ", " + 631 RawContacts.ACCOUNT_NAME + ", " + 632 RawContacts.ACCOUNT_TYPE + ", " + 633 ExtensionsColumns.NAME 634 + " AS " + android.provider.Contacts.Extensions.NAME + ", " + 635 ExtensionsColumns.VALUE 636 + " AS " + android.provider.Contacts.Extensions.VALUE + 637 " FROM " + Tables.DATA_JOIN_MIMETYPE_RAW_CONTACTS + 638 " WHERE " + MimetypesColumns.CONCRETE_MIMETYPE + "='" 639 + android.provider.Contacts.Extensions.CONTENT_ITEM_TYPE + "'" 640 + " AND " + Tables.RAW_CONTACTS + "." + RawContacts.DELETED + "=0" 641 + " AND " + RawContacts.IS_RESTRICTED + "=0" + 642 ";"); 643 644 db.execSQL("DROP VIEW IF EXISTS " + LegacyTables.GROUPS + ";"); 645 db.execSQL("CREATE VIEW " + LegacyTables.GROUPS + " AS SELECT " + 646 GroupsColumns.CONCRETE_ID + " AS " + android.provider.Contacts.Groups._ID + ", " + 647 Groups.ACCOUNT_NAME + ", " + 648 Groups.ACCOUNT_TYPE + ", " + 649 Groups.TITLE + " AS " + android.provider.Contacts.Groups.NAME + ", " + 650 Groups.NOTES + " AS " + android.provider.Contacts.Groups.NOTES + " , " + 651 Groups.SYSTEM_ID + " AS " + android.provider.Contacts.Groups.SYSTEM_ID + 652 " FROM " + Tables.GROUPS + 653 ";"); 654 655 db.execSQL("DROP VIEW IF EXISTS " + LegacyTables.GROUP_MEMBERSHIP + ";"); 656 db.execSQL("CREATE VIEW " + LegacyTables.GROUP_MEMBERSHIP + " AS SELECT " + 657 DataColumns.CONCRETE_ID 658 + " AS " + android.provider.Contacts.GroupMembership._ID + ", " + 659 DataColumns.CONCRETE_RAW_CONTACT_ID 660 + " AS " + android.provider.Contacts.GroupMembership.PERSON_ID + ", " + 661 Tables.RAW_CONTACTS + "." + RawContacts.ACCOUNT_NAME 662 + " AS " + RawContacts.ACCOUNT_NAME + ", " + 663 Tables.RAW_CONTACTS + "." + RawContacts.ACCOUNT_TYPE 664 + " AS " + RawContacts.ACCOUNT_TYPE + ", " + 665 GroupMembership.GROUP_ROW_ID 666 + " AS " + android.provider.Contacts.GroupMembership.GROUP_ID + ", " + 667 Groups.TITLE 668 + " AS " + android.provider.Contacts.GroupMembership.NAME + ", " + 669 Groups.NOTES 670 + " AS " + android.provider.Contacts.GroupMembership.NOTES + " , " + 671 Groups.SYSTEM_ID 672 + " AS " + android.provider.Contacts.GroupMembership.SYSTEM_ID + 673 " FROM " + Tables.DATA_JOIN_PACKAGES_MIMETYPES_RAW_CONTACTS_GROUPS + 674 " WHERE " + MimetypesColumns.CONCRETE_MIMETYPE + "='" 675 + GroupMembership.CONTENT_ITEM_TYPE + "'" 676 + " AND " + Tables.RAW_CONTACTS + "." + RawContacts.DELETED + "=0" + 677 ";"); 678 679 db.execSQL("DROP VIEW IF EXISTS " + LegacyTables.PHOTOS + ";"); 680 db.execSQL("CREATE VIEW " + LegacyTables.PHOTOS + " AS SELECT " + 681 DataColumns.CONCRETE_ID 682 + " AS " + android.provider.Contacts.Photos._ID + ", " + 683 DataColumns.CONCRETE_RAW_CONTACT_ID 684 + " AS " + android.provider.Contacts.Photos.PERSON_ID + ", " + 685 RawContacts.ACCOUNT_NAME + ", " + 686 RawContacts.ACCOUNT_TYPE + ", " + 687 Tables.DATA + "." + Photo.PHOTO 688 + " AS " + android.provider.Contacts.Photos.DATA + ", " + 689 "legacy_photo." + LegacyPhotoData.EXISTS_ON_SERVER 690 + " AS " + android.provider.Contacts.Photos.EXISTS_ON_SERVER + ", " + 691 "legacy_photo." + LegacyPhotoData.DOWNLOAD_REQUIRED 692 + " AS " + android.provider.Contacts.Photos.DOWNLOAD_REQUIRED + ", " + 693 "legacy_photo." + LegacyPhotoData.LOCAL_VERSION 694 + " AS " + android.provider.Contacts.Photos.LOCAL_VERSION + ", " + 695 "legacy_photo." + LegacyPhotoData.SYNC_ERROR 696 + " AS " + android.provider.Contacts.Photos.SYNC_ERROR + 697 " FROM " + Tables.DATA + DATA_JOINS + LEGACY_PHOTO_JOIN + 698 " WHERE " + MimetypesColumns.CONCRETE_MIMETYPE + "='" 699 + Photo.CONTENT_ITEM_TYPE + "'" 700 + " AND " + Tables.RAW_CONTACTS + "." + RawContacts.DELETED + "=0" 701 + " AND " + RawContacts.IS_RESTRICTED + "=0" + 702 ";"); 703 } 704 705 public Uri insert(Uri uri, ContentValues values) { 706 final int match = sUriMatcher.match(uri); 707 long id = 0; 708 switch (match) { 709 case PEOPLE: 710 id = insertPeople(values); 711 break; 712 713 case ORGANIZATIONS: 714 id = insertOrganization(values); 715 break; 716 717 case PEOPLE_CONTACTMETHODS: { 718 long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 719 id = insertContactMethod(rawContactId, values); 720 break; 721 } 722 723 case CONTACTMETHODS: { 724 long rawContactId = getRequiredValue(values, ContactMethods.PERSON_ID); 725 id = insertContactMethod(rawContactId, values); 726 break; 727 } 728 729 case PHONES: { 730 long rawContactId = getRequiredValue(values, 731 android.provider.Contacts.Phones.PERSON_ID); 732 id = insertPhone(rawContactId, values); 733 break; 734 } 735 736 case EXTENSIONS: { 737 long rawContactId = getRequiredValue(values, 738 android.provider.Contacts.Extensions.PERSON_ID); 739 id = insertExtension(rawContactId, values); 740 break; 741 } 742 743 case GROUPS: 744 id = insertGroup(values); 745 break; 746 747 case GROUPMEMBERSHIP: { 748 long rawContactId = getRequiredValue(values, 749 android.provider.Contacts.GroupMembership.PERSON_ID); 750 long groupId = getRequiredValue(values, 751 android.provider.Contacts.GroupMembership.GROUP_ID); 752 id = insertGroupMembership(rawContactId, groupId); 753 break; 754 } 755 756 default: 757 throw new UnsupportedOperationException("Unknown uri: " + uri); 758 } 759 760 if (id < 0) { 761 return null; 762 } 763 764 final Uri result = ContentUris.withAppendedId(uri, id); 765 onChange(result); 766 return result; 767 } 768 769 private long getRequiredValue(ContentValues values, String column) { 770 if (!values.containsKey(column)) { 771 throw new RuntimeException("Required value: " + column); 772 } 773 774 return values.getAsLong(column); 775 } 776 777 private long insertPeople(ContentValues values) { 778 ensureDefaultAccount(); 779 780 mValues.clear(); 781 782 OpenHelper.copyStringValue(mValues, RawContacts.CUSTOM_RINGTONE, 783 values, People.CUSTOM_RINGTONE); 784 OpenHelper.copyLongValue(mValues, RawContacts.SEND_TO_VOICEMAIL, 785 values, People.SEND_TO_VOICEMAIL); 786 OpenHelper.copyLongValue(mValues, RawContacts.LAST_TIME_CONTACTED, 787 values, People.LAST_TIME_CONTACTED); 788 OpenHelper.copyLongValue(mValues, RawContacts.TIMES_CONTACTED, 789 values, People.TIMES_CONTACTED); 790 OpenHelper.copyLongValue(mValues, RawContacts.STARRED, 791 values, People.STARRED); 792 mValues.put(RawContacts.ACCOUNT_NAME, mAccount.name); 793 mValues.put(RawContacts.ACCOUNT_TYPE, mAccount.type); 794 Uri contactUri = mContactsProvider.insert(RawContacts.CONTENT_URI, mValues); 795 long rawContactId = ContentUris.parseId(contactUri); 796 797 if (values.containsKey(People.NAME) || values.containsKey(People.PHONETIC_NAME)) { 798 mValues.clear(); 799 mValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId); 800 mValues.put(ContactsContract.Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); 801 OpenHelper.copyStringValue(mValues, StructuredName.DISPLAY_NAME, 802 values, People.NAME); 803 if (values.containsKey(People.PHONETIC_NAME)) { 804 String phoneticName = values.getAsString(People.PHONETIC_NAME); 805 NameSplitter.Name parsedName = new NameSplitter.Name(); 806 mPhoneticNameSplitter.split(parsedName, phoneticName); 807 mValues.put(StructuredName.PHONETIC_GIVEN_NAME, parsedName.getGivenNames()); 808 mValues.put(StructuredName.PHONETIC_MIDDLE_NAME, parsedName.getMiddleName()); 809 mValues.put(StructuredName.PHONETIC_FAMILY_NAME, parsedName.getFamilyName()); 810 } 811 812 mContactsProvider.insert(ContactsContract.Data.CONTENT_URI, mValues); 813 } 814 815 if (values.containsKey(People.NOTES)) { 816 mValues.clear(); 817 mValues.put(Data.RAW_CONTACT_ID, rawContactId); 818 mValues.put(Data.MIMETYPE, Note.CONTENT_ITEM_TYPE); 819 OpenHelper.copyStringValue(mValues, Note.NOTE, values, People.NOTES); 820 mContactsProvider.insert(Data.CONTENT_URI, mValues); 821 } 822 823 // TODO instant aggregation 824 return rawContactId; 825 } 826 827 private long insertOrganization(ContentValues values) { 828 mValues.clear(); 829 830 OpenHelper.copyLongValue(mValues, Data.RAW_CONTACT_ID, 831 values, android.provider.Contacts.Organizations.PERSON_ID); 832 mValues.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE); 833 834 OpenHelper.copyLongValue(mValues, Data.IS_PRIMARY, 835 values, android.provider.Contacts.Organizations.ISPRIMARY); 836 837 OpenHelper.copyStringValue(mValues, Organization.COMPANY, 838 values, android.provider.Contacts.Organizations.COMPANY); 839 840 // TYPE values happen to remain the same between V1 and V2 - can just copy the value 841 OpenHelper.copyLongValue(mValues, Organization.TYPE, 842 values, android.provider.Contacts.Organizations.TYPE); 843 844 OpenHelper.copyStringValue(mValues, Organization.LABEL, 845 values, android.provider.Contacts.Organizations.LABEL); 846 OpenHelper.copyStringValue(mValues, Organization.TITLE, 847 values, android.provider.Contacts.Organizations.TITLE); 848 849 Uri uri = mContactsProvider.insert(Data.CONTENT_URI, mValues); 850 851 return ContentUris.parseId(uri); 852 } 853 854 private long insertPhone(long rawContactId, ContentValues values) { 855 mValues.clear(); 856 857 mValues.put(Data.RAW_CONTACT_ID, rawContactId); 858 mValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 859 860 OpenHelper.copyLongValue(mValues, Data.IS_PRIMARY, 861 values, android.provider.Contacts.Phones.ISPRIMARY); 862 863 OpenHelper.copyStringValue(mValues, Phone.NUMBER, 864 values, android.provider.Contacts.Phones.NUMBER); 865 866 // TYPE values happen to remain the same between V1 and V2 - can just copy the value 867 OpenHelper.copyLongValue(mValues, Phone.TYPE, 868 values, android.provider.Contacts.Phones.TYPE); 869 870 OpenHelper.copyStringValue(mValues, Phone.LABEL, 871 values, android.provider.Contacts.Phones.LABEL); 872 873 Uri uri = mContactsProvider.insert(Data.CONTENT_URI, mValues); 874 875 return ContentUris.parseId(uri); 876 } 877 878 private long insertContactMethod(long rawContactId, ContentValues values) { 879 Integer kind = values.getAsInteger(ContactMethods.KIND); 880 if (kind == null) { 881 throw new RuntimeException("Required value: " + ContactMethods.KIND); 882 } 883 884 mValues.clear(); 885 mValues.put(Data.RAW_CONTACT_ID, rawContactId); 886 887 OpenHelper.copyLongValue(mValues, Data.IS_PRIMARY, values, ContactMethods.ISPRIMARY); 888 889 switch (kind) { 890 case android.provider.Contacts.KIND_EMAIL: { 891 copyCommonFields(values, Email.CONTENT_ITEM_TYPE, Email.TYPE, Email.LABEL, 892 Data.DATA14); 893 OpenHelper.copyStringValue(mValues, Email.DATA, values, ContactMethods.DATA); 894 break; 895 } 896 897 case android.provider.Contacts.KIND_IM: { 898 String protocol = values.getAsString(ContactMethods.DATA); 899 if (protocol.startsWith("pre:")) { 900 mValues.put(Im.PROTOCOL, Integer.parseInt(protocol.substring(4))); 901 } else if (protocol.startsWith("custom:")) { 902 mValues.put(Im.PROTOCOL, Im.PROTOCOL_CUSTOM); 903 mValues.put(Im.CUSTOM_PROTOCOL, protocol.substring(7)); 904 } 905 906 copyCommonFields(values, Im.CONTENT_ITEM_TYPE, Im.TYPE, Im.LABEL, Data.DATA14); 907 break; 908 } 909 910 case android.provider.Contacts.KIND_POSTAL: { 911 copyCommonFields(values, StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, 912 StructuredPostal.LABEL, Data.DATA14); 913 OpenHelper.copyStringValue(mValues, StructuredPostal.FORMATTED_ADDRESS, values, 914 ContactMethods.DATA); 915 break; 916 } 917 } 918 919 Uri uri = mContactsProvider.insert(Data.CONTENT_URI, mValues); 920 return ContentUris.parseId(uri); 921 } 922 923 private void copyCommonFields(ContentValues values, String mimeType, String typeColumn, 924 String labelColumn, String auxDataColumn) { 925 mValues.put(Data.MIMETYPE, mimeType); 926 OpenHelper.copyLongValue(mValues, typeColumn, values, ContactMethods.TYPE); 927 OpenHelper.copyStringValue(mValues, labelColumn, values, ContactMethods.LABEL); 928 OpenHelper.copyStringValue(mValues, auxDataColumn, values, ContactMethods.AUX_DATA); 929 } 930 931 private long insertExtension(long rawContactId, ContentValues values) { 932 mValues.clear(); 933 934 mValues.put(Data.RAW_CONTACT_ID, rawContactId); 935 mValues.put(Data.MIMETYPE, android.provider.Contacts.Extensions.CONTENT_ITEM_TYPE); 936 937 OpenHelper.copyStringValue(mValues, ExtensionsColumns.NAME, 938 values, android.provider.Contacts.People.Extensions.NAME); 939 OpenHelper.copyStringValue(mValues, ExtensionsColumns.VALUE, 940 values, android.provider.Contacts.People.Extensions.VALUE); 941 942 Uri uri = mContactsProvider.insert(Data.CONTENT_URI, mValues); 943 return ContentUris.parseId(uri); 944 } 945 946 private long insertGroup(ContentValues values) { 947 ensureDefaultAccount(); 948 mValues.clear(); 949 950 OpenHelper.copyStringValue(mValues, Groups.TITLE, 951 values, android.provider.Contacts.Groups.NAME); 952 OpenHelper.copyStringValue(mValues, Groups.NOTES, 953 values, android.provider.Contacts.Groups.NOTES); 954 OpenHelper.copyStringValue(mValues, Groups.SYSTEM_ID, 955 values, android.provider.Contacts.Groups.SYSTEM_ID); 956 957 mValues.put(Groups.ACCOUNT_NAME, mAccount.name); 958 mValues.put(Groups.ACCOUNT_TYPE, mAccount.type); 959 960 Uri uri = mContactsProvider.insert(Groups.CONTENT_URI, mValues); 961 return ContentUris.parseId(uri); 962 } 963 964 private long insertGroupMembership(long rawContactId, long groupId) { 965 mValues.clear(); 966 967 mValues.put(Data.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE); 968 mValues.put(GroupMembership.RAW_CONTACT_ID, rawContactId); 969 mValues.put(GroupMembership.GROUP_ROW_ID, groupId); 970 971 Uri uri = mContactsProvider.insert(Data.CONTENT_URI, mValues); 972 return ContentUris.parseId(uri); 973 } 974 975 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 976 final int match = sUriMatcher.match(uri); 977 int count = 0; 978 switch(match) { 979 case PEOPLE_UPDATE_CONTACT_TIME: 980 count = updateContactTime(uri, values); 981 break; 982 983 case PEOPLE_PHOTO: { 984 long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 985 return updatePhoto(rawContactId, values); 986 } 987 988 case PHOTOS: 989 // TODO 990 break; 991 992 case PHOTOS_ID: 993 // TODO 994 break; 995 996 997 default: 998 throw new UnsupportedOperationException("Unknown uri: " + uri); 999 } 1000 1001 if (count > 0) { 1002 mContext.getContentResolver().notifyChange(uri, null); 1003 } 1004 return count; 1005 } 1006 1007 1008 private int updateContactTime(Uri uri, ContentValues values) { 1009 1010 // TODO check sanctions 1011 1012 long lastTimeContacted; 1013 if (values.containsKey(People.LAST_TIME_CONTACTED)) { 1014 lastTimeContacted = values.getAsLong(People.LAST_TIME_CONTACTED); 1015 } else { 1016 lastTimeContacted = System.currentTimeMillis(); 1017 } 1018 1019 long rawContactId = Long.parseLong(uri.getPathSegments().get(1)); 1020 long contactId = mOpenHelper.getContactId(rawContactId); 1021 if (contactId != 0) { 1022 mContactsProvider.updateContactTime(contactId, lastTimeContacted); 1023 } else { 1024 mLastTimeContactedUpdate.bindLong(1, lastTimeContacted); 1025 mLastTimeContactedUpdate.bindLong(2, rawContactId); 1026 mLastTimeContactedUpdate.execute(); 1027 } 1028 return 1; 1029 } 1030 1031 private int updatePhoto(long rawContactId, ContentValues values) { 1032 1033 // TODO check sanctions 1034 1035 int count; 1036 1037 long dataId = -1; 1038 Cursor c = mContactsProvider.query(Data.CONTENT_URI, PhotoQuery.COLUMNS, 1039 Data.RAW_CONTACT_ID + "=" + rawContactId + " AND " 1040 + Data.MIMETYPE + "=" + mOpenHelper.getMimeTypeId(Photo.CONTENT_ITEM_TYPE), 1041 null, null); 1042 try { 1043 if (c.moveToFirst()) { 1044 dataId = c.getLong(PhotoQuery._ID); 1045 } 1046 } finally { 1047 c.close(); 1048 } 1049 1050 mValues.clear(); 1051 byte[] bytes = values.getAsByteArray(android.provider.Contacts.Photos.DATA); 1052 mValues.put(Photo.PHOTO, bytes); 1053 1054 if (dataId == -1) { 1055 mValues.put(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE); 1056 mValues.put(Data.RAW_CONTACT_ID, rawContactId); 1057 Uri dataUri = mContactsProvider.insert(Data.CONTENT_URI, mValues); 1058 dataId = ContentUris.parseId(dataUri); 1059 count = 1; 1060 } else { 1061 Uri dataUri = ContentUris.withAppendedId(Data.CONTENT_URI, dataId); 1062 count = mContactsProvider.update(dataUri, mValues, null, null); 1063 } 1064 1065 mValues.clear(); 1066 OpenHelper.copyStringValue(mValues, LegacyPhotoData.LOCAL_VERSION, 1067 values, android.provider.Contacts.Photos.LOCAL_VERSION); 1068 OpenHelper.copyStringValue(mValues, LegacyPhotoData.DOWNLOAD_REQUIRED, 1069 values, android.provider.Contacts.Photos.DOWNLOAD_REQUIRED); 1070 OpenHelper.copyStringValue(mValues, LegacyPhotoData.EXISTS_ON_SERVER, 1071 values, android.provider.Contacts.Photos.EXISTS_ON_SERVER); 1072 OpenHelper.copyStringValue(mValues, LegacyPhotoData.SYNC_ERROR, 1073 values, android.provider.Contacts.Photos.SYNC_ERROR); 1074 1075 int updated = mContactsProvider.update(Data.CONTENT_URI, mValues, 1076 Data.MIMETYPE + "='" + LegacyPhotoData.CONTENT_ITEM_TYPE + "'" 1077 + " AND " + Data.RAW_CONTACT_ID + "=" + rawContactId 1078 + " AND " + LegacyPhotoData.PHOTO_DATA_ID + "=" + dataId, null); 1079 if (updated == 0) { 1080 mValues.put(Data.RAW_CONTACT_ID, rawContactId); 1081 mValues.put(Data.MIMETYPE, LegacyPhotoData.CONTENT_ITEM_TYPE); 1082 mValues.put(LegacyPhotoData.PHOTO_DATA_ID, dataId); 1083 mContactsProvider.insert(Data.CONTENT_URI, mValues); 1084 } 1085 1086 return count; 1087 } 1088 1089 public int delete(Uri uri, String selection, String[] selectionArgs) { 1090 final int match = sUriMatcher.match(uri); 1091 int count = 0; 1092 switch (match) { 1093 case PEOPLE_ID: 1094 count = mContactsProvider.deleteRawContact(ContentUris.parseId(uri), false); 1095 break; 1096 1097 case ORGANIZATIONS_ID: 1098 count = mContactsProvider.deleteData(ContentUris.parseId(uri), 1099 ORGANIZATION_MIME_TYPES); 1100 break; 1101 1102 case CONTACTMETHODS_ID: 1103 count = mContactsProvider.deleteData(ContentUris.parseId(uri), 1104 CONTACT_METHOD_MIME_TYPES); 1105 break; 1106 1107 case PHONES_ID: 1108 count = mContactsProvider.deleteData(ContentUris.parseId(uri), 1109 PHONE_MIME_TYPES); 1110 break; 1111 1112 default: 1113 throw new UnsupportedOperationException("Unknown uri: " + uri); 1114 } 1115 1116 return count; 1117 } 1118 1119 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 1120 String sortOrder, String limit) { 1121 ensureDefaultAccount(); 1122 1123 final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 1124 SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 1125 String groupBy = null; 1126 1127 final int match = sUriMatcher.match(uri); 1128 switch (match) { 1129 case PEOPLE: { 1130 qb.setTables(LegacyTables.PEOPLE_JOIN_PRESENCE); 1131 qb.setProjectionMap(sPeopleProjectionMap); 1132 applyRawContactsAccount(qb, uri); 1133 break; 1134 } 1135 1136 case PEOPLE_ID: 1137 qb.setTables(LegacyTables.PEOPLE_JOIN_PRESENCE); 1138 qb.setProjectionMap(sPeopleProjectionMap); 1139 applyRawContactsAccount(qb, uri); 1140 qb.appendWhere(" AND " + People._ID + "="); 1141 qb.appendWhere(uri.getPathSegments().get(1)); 1142 break; 1143 1144 case PEOPLE_FILTER: { 1145 qb.setTables(LegacyTables.PEOPLE_JOIN_PRESENCE); 1146 qb.setProjectionMap(sPeopleProjectionMap); 1147 applyRawContactsAccount(qb, uri); 1148 String filterParam = uri.getPathSegments().get(2); 1149 qb.appendWhere(" AND " + People._ID + " IN " 1150 + mContactsProvider.getRawContactsByFilterAsNestedQuery(filterParam)); 1151 break; 1152 } 1153 1154 case ORGANIZATIONS: 1155 qb.setTables(LegacyTables.ORGANIZATIONS); 1156 qb.setProjectionMap(sOrganizationProjectionMap); 1157 applyRawContactsAccount(qb, uri); 1158 break; 1159 1160 case ORGANIZATIONS_ID: 1161 qb.setTables(LegacyTables.ORGANIZATIONS); 1162 qb.setProjectionMap(sOrganizationProjectionMap); 1163 applyRawContactsAccount(qb, uri); 1164 qb.appendWhere(" AND " + android.provider.Contacts.Organizations._ID + "="); 1165 qb.appendWhere(uri.getPathSegments().get(1)); 1166 break; 1167 1168 case CONTACTMETHODS: 1169 qb.setTables(LegacyTables.CONTACT_METHODS); 1170 qb.setProjectionMap(sContactMethodProjectionMap); 1171 applyRawContactsAccount(qb, uri); 1172 break; 1173 1174 case CONTACTMETHODS_ID: 1175 qb.setTables(LegacyTables.CONTACT_METHODS); 1176 qb.setProjectionMap(sContactMethodProjectionMap); 1177 applyRawContactsAccount(qb, uri); 1178 qb.appendWhere(" AND " + ContactMethods._ID + "="); 1179 qb.appendWhere(uri.getPathSegments().get(1)); 1180 break; 1181 1182 case PEOPLE_CONTACTMETHODS: 1183 qb.setTables(LegacyTables.CONTACT_METHODS); 1184 qb.setProjectionMap(sContactMethodProjectionMap); 1185 applyRawContactsAccount(qb, uri); 1186 qb.appendWhere(" AND " + ContactMethods.PERSON_ID + "="); 1187 qb.appendWhere(uri.getPathSegments().get(1)); 1188 qb.appendWhere(" AND " + ContactMethods.KIND + " IS NOT NULL"); 1189 break; 1190 1191 case PEOPLE_CONTACTMETHODS_ID: 1192 qb.setTables(LegacyTables.CONTACT_METHODS); 1193 qb.setProjectionMap(sContactMethodProjectionMap); 1194 applyRawContactsAccount(qb, uri); 1195 qb.appendWhere(" AND " + ContactMethods.PERSON_ID + "="); 1196 qb.appendWhere(uri.getPathSegments().get(1)); 1197 qb.appendWhere(" AND " + ContactMethods._ID + "="); 1198 qb.appendWhere(uri.getPathSegments().get(3)); 1199 qb.appendWhere(" AND " + ContactMethods.KIND + " IS NOT NULL"); 1200 break; 1201 1202 case PHONES: 1203 qb.setTables(LegacyTables.PHONES); 1204 qb.setProjectionMap(sPhoneProjectionMap); 1205 applyRawContactsAccount(qb, uri); 1206 break; 1207 1208 case PHONES_ID: 1209 qb.setTables(LegacyTables.PHONES); 1210 qb.setProjectionMap(sPhoneProjectionMap); 1211 applyRawContactsAccount(qb, uri); 1212 qb.appendWhere(" AND " + android.provider.Contacts.Phones._ID + "="); 1213 qb.appendWhere(uri.getPathSegments().get(1)); 1214 break; 1215 1216 case PHONES_FILTER: 1217 qb.setTables(LegacyTables.PHONES); 1218 qb.setProjectionMap(sPhoneProjectionMap); 1219 applyRawContactsAccount(qb, uri); 1220 if (uri.getPathSegments().size() > 2) { 1221 String filterParam = uri.getLastPathSegment(); 1222 qb.appendWhere(" AND person ="); 1223 qb.appendWhere(mOpenHelper.buildPhoneLookupAsNestedQuery(filterParam)); 1224 } 1225 break; 1226 1227 case PEOPLE_PHONES: 1228 qb.setTables(LegacyTables.PHONES); 1229 qb.setProjectionMap(sPhoneProjectionMap); 1230 applyRawContactsAccount(qb, uri); 1231 qb.appendWhere(" AND " + android.provider.Contacts.Phones.PERSON_ID + "="); 1232 qb.appendWhere(uri.getPathSegments().get(1)); 1233 break; 1234 1235 case PEOPLE_PHONES_ID: 1236 qb.setTables(LegacyTables.PHONES); 1237 qb.setProjectionMap(sPhoneProjectionMap); 1238 applyRawContactsAccount(qb, uri); 1239 qb.appendWhere(" AND " + android.provider.Contacts.Phones.PERSON_ID + "="); 1240 qb.appendWhere(uri.getPathSegments().get(1)); 1241 qb.appendWhere(" AND " + android.provider.Contacts.Phones._ID + "="); 1242 qb.appendWhere(uri.getPathSegments().get(3)); 1243 break; 1244 1245 case EXTENSIONS: 1246 qb.setTables(LegacyTables.EXTENSIONS); 1247 qb.setProjectionMap(sExtensionProjectionMap); 1248 applyRawContactsAccount(qb, uri); 1249 break; 1250 1251 case EXTENSIONS_ID: 1252 qb.setTables(LegacyTables.EXTENSIONS); 1253 qb.setProjectionMap(sExtensionProjectionMap); 1254 applyRawContactsAccount(qb, uri); 1255 qb.appendWhere(" AND " + android.provider.Contacts.Extensions._ID + "="); 1256 qb.appendWhere(uri.getPathSegments().get(1)); 1257 break; 1258 1259 case PEOPLE_EXTENSIONS: 1260 qb.setTables(LegacyTables.EXTENSIONS); 1261 qb.setProjectionMap(sExtensionProjectionMap); 1262 applyRawContactsAccount(qb, uri); 1263 qb.appendWhere(" AND " + android.provider.Contacts.Extensions.PERSON_ID + "="); 1264 qb.appendWhere(uri.getPathSegments().get(1)); 1265 break; 1266 1267 case PEOPLE_EXTENSIONS_ID: 1268 qb.setTables(LegacyTables.EXTENSIONS); 1269 qb.setProjectionMap(sExtensionProjectionMap); 1270 applyRawContactsAccount(qb, uri); 1271 qb.appendWhere(" AND " + android.provider.Contacts.Extensions.PERSON_ID + "="); 1272 qb.appendWhere(uri.getPathSegments().get(1)); 1273 qb.appendWhere(" AND " + android.provider.Contacts.Extensions._ID + "="); 1274 qb.appendWhere(uri.getPathSegments().get(3)); 1275 break; 1276 1277 case GROUPS: 1278 qb.setTables(LegacyTables.GROUPS); 1279 qb.setProjectionMap(sGroupProjectionMap); 1280 applyGroupAccount(qb, uri); 1281 break; 1282 1283 case GROUPS_ID: 1284 qb.setTables(LegacyTables.GROUPS); 1285 qb.setProjectionMap(sGroupProjectionMap); 1286 applyGroupAccount(qb, uri); 1287 qb.appendWhere(" AND " + android.provider.Contacts.Groups._ID + "="); 1288 qb.appendWhere(uri.getPathSegments().get(1)); 1289 break; 1290 1291 case GROUPMEMBERSHIP: 1292 qb.setTables(LegacyTables.GROUP_MEMBERSHIP); 1293 qb.setProjectionMap(sGroupMembershipProjectionMap); 1294 applyRawContactsAccount(qb, uri); 1295 break; 1296 1297 case GROUPMEMBERSHIP_ID: 1298 qb.setTables(LegacyTables.GROUP_MEMBERSHIP); 1299 qb.setProjectionMap(sGroupMembershipProjectionMap); 1300 applyRawContactsAccount(qb, uri); 1301 qb.appendWhere(" AND " + android.provider.Contacts.GroupMembership._ID + "="); 1302 qb.appendWhere(uri.getPathSegments().get(1)); 1303 break; 1304 1305 case PEOPLE_GROUPMEMBERSHIP: 1306 qb.setTables(LegacyTables.GROUP_MEMBERSHIP); 1307 qb.setProjectionMap(sGroupMembershipProjectionMap); 1308 applyRawContactsAccount(qb, uri); 1309 qb.appendWhere(" AND " + android.provider.Contacts.GroupMembership.PERSON_ID + "="); 1310 qb.appendWhere(uri.getPathSegments().get(1)); 1311 break; 1312 1313 case PEOPLE_GROUPMEMBERSHIP_ID: 1314 qb.setTables(LegacyTables.GROUP_MEMBERSHIP); 1315 qb.setProjectionMap(sGroupMembershipProjectionMap); 1316 applyRawContactsAccount(qb, uri); 1317 qb.appendWhere(" AND " + android.provider.Contacts.GroupMembership.PERSON_ID + "="); 1318 qb.appendWhere(uri.getPathSegments().get(1)); 1319 qb.appendWhere(" AND " + android.provider.Contacts.GroupMembership._ID + "="); 1320 qb.appendWhere(uri.getPathSegments().get(3)); 1321 break; 1322 1323 case PEOPLE_PHOTO: 1324 qb.setTables(LegacyTables.PHOTOS); 1325 qb.setProjectionMap(sPhotoProjectionMap); 1326 applyRawContactsAccount(qb, uri); 1327 qb.appendWhere(" AND " + android.provider.Contacts.Photos.PERSON_ID + "="); 1328 qb.appendWhere(uri.getPathSegments().get(1)); 1329 limit = "1"; 1330 break; 1331 1332 case SEARCH_SUGGESTIONS: 1333 1334 // No legacy compatibility for search suggestions 1335 return mGlobalSearchSupport.handleSearchSuggestionsQuery(db, uri, limit); 1336 1337 case DELETED_PEOPLE: 1338 case DELETED_GROUPS: 1339 throw new UnsupportedOperationException(); 1340 1341 default: 1342 throw new IllegalArgumentException("Unknown URL " + uri); 1343 } 1344 1345 // Perform the query and set the notification uri 1346 final Cursor c = qb.query(db, projection, selection, selectionArgs, 1347 groupBy, null, sortOrder, limit); 1348 if (c != null) { 1349 c.setNotificationUri(mContext.getContentResolver(), RawContacts.CONTENT_URI); 1350 } 1351 return c; 1352 } 1353 1354 private void applyRawContactsAccount(SQLiteQueryBuilder qb, Uri uri) { 1355 StringBuilder sb = new StringBuilder(); 1356 sb.append(RawContacts.ACCOUNT_NAME + "="); 1357 DatabaseUtils.appendEscapedSQLString(sb, mAccount.name); 1358 sb.append(" AND " + RawContacts.ACCOUNT_TYPE + "="); 1359 DatabaseUtils.appendEscapedSQLString(sb, mAccount.type); 1360 qb.appendWhere(sb.toString()); 1361 } 1362 1363 private void applyGroupAccount(SQLiteQueryBuilder qb, Uri uri) { 1364 StringBuilder sb = new StringBuilder(); 1365 sb.append(Groups.ACCOUNT_NAME + "="); 1366 DatabaseUtils.appendEscapedSQLString(sb, mAccount.name); 1367 sb.append(" AND " + Groups.ACCOUNT_TYPE + "="); 1368 DatabaseUtils.appendEscapedSQLString(sb, mAccount.type); 1369 qb.appendWhere(sb.toString()); 1370 } 1371 1372 /** 1373 * Called when a change has been made. 1374 * 1375 * @param uri the uri that the change was made to 1376 */ 1377 private void onChange(Uri uri) { 1378 mContext.getContentResolver().notifyChange(android.provider.Contacts.CONTENT_URI, null); 1379 } 1380} 1381