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