summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitri Plotnikov <dplotnikov@google.com>2010-03-30 18:06:23 -0700
committerDmitri Plotnikov <dplotnikov@google.com>2010-03-30 18:06:23 -0700
commit33fd566fb6eebdd40a900c0c8a2f6dca894d7829 (patch)
treea9af3f488eaa294f0f2ae756493007935d244972
parent6dddb9abd6f738e43b41a4687c318533085ff0c7 (diff)
downloadandroid_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
-rw-r--r--src/com/android/providers/contacts/ContactsDatabaseHelper.java3
-rw-r--r--src/com/android/providers/contacts/ContactsProvider2.java28
-rw-r--r--tests/src/com/android/providers/contacts/ContactsProvider2Test.java40
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");