diff options
author | Dmitri Plotnikov <dplotnikov@google.com> | 2010-03-30 18:06:23 -0700 |
---|---|---|
committer | Dmitri Plotnikov <dplotnikov@google.com> | 2010-03-30 18:06:23 -0700 |
commit | 33fd566fb6eebdd40a900c0c8a2f6dca894d7829 (patch) | |
tree | a9af3f488eaa294f0f2ae756493007935d244972 | |
parent | 6dddb9abd6f738e43b41a4687c318533085ff0c7 (diff) | |
download | android_packages_providers_ContactsProvider-33fd566fb6eebdd40a900c0c8a2f6dca894d7829.tar.gz android_packages_providers_ContactsProvider-33fd566fb6eebdd40a900c0c8a2f6dca894d7829.tar.bz2 android_packages_providers_ContactsProvider-33fd566fb6eebdd40a900c0c8a2f6dca894d7829.zip |
Cleaning up dangling pointers after account removal.
An aggregated contact points at a raw contact that
contains the contact name. It also points at a photo
row. When we remove an account, we should be fixing
up those pointers. That's exactly what is done
in this CL.
Bug:2557771
Change-Id: I04bc6b23be31ed53b27b48bd2f92eaa1a0838387
3 files changed, 71 insertions, 0 deletions
diff --git a/src/com/android/providers/contacts/ContactsDatabaseHelper.java b/src/com/android/providers/contacts/ContactsDatabaseHelper.java index 3f13c5e1..468a63e3 100644 --- a/src/com/android/providers/contacts/ContactsDatabaseHelper.java +++ b/src/com/android/providers/contacts/ContactsDatabaseHelper.java @@ -2502,6 +2502,9 @@ import java.util.Locale; public void wipeData() { SQLiteDatabase db = getWritableDatabase(); + db.execSQL("DELETE FROM " + Tables.ACCOUNTS + ";"); + db.execSQL("INSERT INTO accounts VALUES(NULL, NULL)"); + db.execSQL("DELETE FROM " + Tables.CONTACTS + ";"); db.execSQL("DELETE FROM " + Tables.RAW_CONTACTS + ";"); db.execSQL("DELETE FROM " + Tables.DATA + ";"); diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java index 04fb9e30..43b9e122 100644 --- a/src/com/android/providers/contacts/ContactsProvider2.java +++ b/src/com/android/providers/contacts/ContactsProvider2.java @@ -4031,6 +4031,34 @@ public class ContactsProvider2 extends SQLiteContentProvider implements OnAccoun " AND " + RawContacts.ACCOUNT_TYPE + "=?", params); } + if (!accountsToDelete.isEmpty()) { + // Find all aggregated contacts that used to contain the raw contacts + // we have just deleted and see if they are still referencing the deleted + // names of photos. If so, fix up those contacts. + HashSet<Long> orphanContactIds = Sets.newHashSet(); + Cursor cursor = mDb.rawQuery("SELECT " + Contacts._ID + + " FROM " + Tables.CONTACTS + + " WHERE (" + Contacts.NAME_RAW_CONTACT_ID + " NOT NULL AND " + + Contacts.NAME_RAW_CONTACT_ID + " NOT IN" + + " (SELECT " + RawContacts._ID + + " FROM " + Tables.RAW_CONTACTS + "))" + + " OR (" + Contacts.PHOTO_ID + " NOT NULL AND " + + Contacts.PHOTO_ID + " NOT IN " + + "(SELECT " + Data._ID + + " FROM " + Tables.DATA + "))", null); + try { + while (cursor.moveToNext()) { + orphanContactIds.add(cursor.getLong(0)); + } + } finally { + cursor.close(); + } + + for (Long contactId : orphanContactIds) { + mContactAggregator.updateAggregateData(contactId); + } + } + if (hasUnassignedContacts[0]) { Account primaryAccount = null; diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java index 728f6336..73753314 100644 --- a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java +++ b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java @@ -1752,6 +1752,46 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test { + rawContactId2, null)); } + public void testAccountDeletion() { + Account readOnlyAccount = new Account("act", READ_ONLY_ACCOUNT_TYPE); + ContactsProvider2 cp = (ContactsProvider2) getProvider(); + cp.onAccountsUpdated(new Account[]{readOnlyAccount, mAccount}); + + long rawContactId1 = createRawContactWithName("John", "Doe", readOnlyAccount); + Uri photoUri1 = insertPhoto(rawContactId1); + long rawContactId2 = createRawContactWithName("john", "doe", mAccount); + Uri photoUri2 = insertPhoto(rawContactId2); + storeValue(photoUri2, Photo.IS_SUPER_PRIMARY, "1"); + + assertAggregated(rawContactId1, rawContactId2); + + long contactId = queryContactId(rawContactId1); + + // The display name should come from the writable account + assertStoredValue(Uri.withAppendedPath( + ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), + Contacts.Data.CONTENT_DIRECTORY), + Contacts.DISPLAY_NAME, "john doe"); + + // The photo should be the one we marked as super-primary + assertStoredValue(Contacts.CONTENT_URI, contactId, + Contacts.PHOTO_ID, ContentUris.parseId(photoUri2)); + + // Remove the writable account + cp.onAccountsUpdated(new Account[]{readOnlyAccount}); + + // The display name should come from the remaining account + assertStoredValue(Uri.withAppendedPath( + ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), + Contacts.Data.CONTENT_DIRECTORY), + Contacts.DISPLAY_NAME, "John Doe"); + + // The photo should be the remaining one + assertStoredValue(Contacts.CONTENT_URI, contactId, + Contacts.PHOTO_ID, ContentUris.parseId(photoUri1)); + + } + public void testContactDeletion() { long rawContactId1 = createRawContactWithName("John", "Doe"); long rawContactId2 = createRawContactWithName("John", "Doe"); |