diff options
author | Daniel Lehmann <lehmannd@google.com> | 2010-11-23 17:37:18 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-11-23 17:37:18 -0800 |
commit | fdcf0d5bef479819f9715c0bc750d1e8fa0dcd3e (patch) | |
tree | a1216358abeb976c1f5094fa36e8cb0e845bf278 | |
parent | 359c52a6988dd3e2db2327ec36e5870906fbf359 (diff) | |
parent | 6dd371aea88e09cbe56b8c483021f3bf61527331 (diff) | |
download | packages_providers_ContactsProvider-fdcf0d5bef479819f9715c0bc750d1e8fa0dcd3e.zip packages_providers_ContactsProvider-fdcf0d5bef479819f9715c0bc750d1e8fa0dcd3e.tar.gz packages_providers_ContactsProvider-fdcf0d5bef479819f9715c0bc750d1e8fa0dcd3e.tar.bz2 |
Merge "Allow zeroing the primary/super-primary flag"
-rw-r--r-- | src/com/android/providers/contacts/ContactsProvider2.java | 159 | ||||
-rw-r--r-- | tests/src/com/android/providers/contacts/ContactsProvider2Test.java | 159 |
2 files changed, 283 insertions, 35 deletions
diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java index 01dd6a1..3c5f6ed 100644 --- a/src/com/android/providers/contacts/ContactsProvider2.java +++ b/src/com/android/providers/contacts/ContactsProvider2.java @@ -832,6 +832,8 @@ public class ContactsProvider2 extends SQLiteContentProvider implements OnAccoun private SQLiteStatement mSetPrimaryStatement; /** Precompiled sql statement for setting a data record to the super primary. */ private SQLiteStatement mSetSuperPrimaryStatement; + /** Precompiled sql statement for clearing super primary of a single record. */ + private SQLiteStatement mClearSuperPrimaryStatement; /** Precompiled sql statement for updating a contact display name */ private SQLiteStatement mRawContactDisplayNameUpdate; @@ -999,9 +1001,27 @@ public class ContactsProvider2 extends SQLiteContentProvider implements OnAccoun public long insert(SQLiteDatabase db, long rawContactId, ContentValues values) { final long dataId = db.insert(Tables.DATA, null, values); - Integer primary = values.getAsInteger(Data.IS_PRIMARY); - if (primary != null && primary != 0) { - setIsPrimary(rawContactId, dataId, getMimeTypeId()); + final Integer primary = values.getAsInteger(Data.IS_PRIMARY); + final Integer superPrimary = values.getAsInteger(Data.IS_SUPER_PRIMARY); + if ((primary != null && primary != 0) || (superPrimary != null && superPrimary != 0)) { + final long mimeTypeId = getMimeTypeId(); + setIsPrimary(rawContactId, dataId, mimeTypeId); + + // We also have to make sure that no other data item on this raw_contact is + // configured super primary + if (superPrimary != null) { + if (superPrimary != 0) { + setIsSuperPrimary(rawContactId, dataId, mimeTypeId); + } else { + clearSuperPrimary(rawContactId, mimeTypeId); + } + } else { + // if there is already another data item configured as super-primary, + // take over the flag (which will automatically remove it from the other item) + if (rawContactHasSuperPrimary(rawContactId, mimeTypeId)) { + setIsSuperPrimary(rawContactId, dataId, mimeTypeId); + } + } } return dataId; @@ -1018,20 +1038,7 @@ public class ContactsProvider2 extends SQLiteContentProvider implements OnAccoun long dataId = c.getLong(DataUpdateQuery._ID); long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); - if (values.containsKey(Data.IS_SUPER_PRIMARY)) { - long mimeTypeId = getMimeTypeId(); - setIsSuperPrimary(rawContactId, dataId, mimeTypeId); - setIsPrimary(rawContactId, dataId, mimeTypeId); - - // Now that we've taken care of setting these, remove them from "values". - values.remove(Data.IS_SUPER_PRIMARY); - values.remove(Data.IS_PRIMARY); - } else if (values.containsKey(Data.IS_PRIMARY)) { - setIsPrimary(rawContactId, dataId, getMimeTypeId()); - - // Now that we've taken care of setting this, remove it from "values". - values.remove(Data.IS_PRIMARY); - } + handlePrimaryAndSuperPrimary(values, dataId, rawContactId); if (values.size() > 0) { mSelectionArgs1[0] = String.valueOf(dataId); @@ -1045,6 +1052,72 @@ public class ContactsProvider2 extends SQLiteContentProvider implements OnAccoun return true; } + /** + * Ensures that all super-primary and primary flags of this raw_contact are + * configured correctly + */ + private void handlePrimaryAndSuperPrimary(ContentValues values, long dataId, + long rawContactId) { + final boolean hasPrimary = values.containsKey(Data.IS_PRIMARY); + final boolean hasSuperPrimary = values.containsKey(Data.IS_SUPER_PRIMARY); + + // Nothing to do? Bail out early + if (!hasPrimary && !hasSuperPrimary) return; + + final long mimeTypeId = getMimeTypeId(); + + // Check if we want to clear values + final boolean clearPrimary = hasPrimary && + values.getAsInteger(Data.IS_PRIMARY) == 0; + final boolean clearSuperPrimary = hasSuperPrimary && + values.getAsInteger(Data.IS_SUPER_PRIMARY) == 0; + + if (clearPrimary || clearSuperPrimary) { + // Test whether these values are currently set + final Uri dataUri = ContentUris.withAppendedId(Data.CONTENT_URI, dataId); + final String[] cols = new String[] { Data.IS_PRIMARY, Data.IS_SUPER_PRIMARY }; + final Cursor c = query(dataUri, cols , null, null, null); + try { + if (c.moveToFirst()) { + final boolean isPrimary = c.getInt(0) != 0; + final boolean isSuperPrimary = c.getInt(1) != 0; + // Clear values if they are currently set + if (isSuperPrimary) { + clearSuperPrimary(rawContactId, mimeTypeId); + } + if (clearPrimary && isPrimary) { + setIsPrimary(rawContactId, -1, mimeTypeId); + } + } + } finally { + c.close(); + } + } else { + // Check if we want to set values + final boolean setPrimary = hasPrimary && + values.getAsInteger(Data.IS_PRIMARY) != 0; + final boolean setSuperPrimary = hasSuperPrimary && + values.getAsInteger(Data.IS_SUPER_PRIMARY) != 0; + if (setSuperPrimary) { + // Set both super primary and primary + setIsSuperPrimary(rawContactId, dataId, mimeTypeId); + setIsPrimary(rawContactId, dataId, mimeTypeId); + } else if (setPrimary) { + // Primary was explicitely set, but super-primary was not. + // In this case we set super-primary on this data item, if + // any data item of the same raw-contact already is super-primary + if (rawContactHasSuperPrimary(rawContactId, mimeTypeId)) { + setIsSuperPrimary(rawContactId, dataId, mimeTypeId); + } + setIsPrimary(rawContactId, dataId, mimeTypeId); + } + } + + // Now that we've taken care of clearing this, remove it from "values". + values.remove(Data.IS_SUPER_PRIMARY); + values.remove(Data.IS_PRIMARY); + } + public int delete(SQLiteDatabase db, Cursor c) { long dataId = c.getLong(DataDeleteQuery._ID); long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); @@ -1947,6 +2020,12 @@ public class ContactsProvider2 extends SQLiteContentProvider implements OnAccoun " FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts._ID + "=?))"); + mClearSuperPrimaryStatement = mDb.compileStatement( + "UPDATE " + Tables.DATA + + " SET " + Data.IS_SUPER_PRIMARY + "=0" + + " WHERE " + DataColumns.MIMETYPE_ID + "=?" + + " AND " + Data.RAW_CONTACT_ID + "=?"); + mRawContactDisplayNameUpdate = mDb.compileStatement( "UPDATE " + Tables.RAW_CONTACTS + " SET " + @@ -4024,20 +4103,6 @@ public class ContactsProvider2 extends SQLiteContentProvider implements OnAccoun mValues.put(DataColumns.PACKAGE_ID, mDbHelper.getPackageId(packageName)); } - boolean containsIsSuperPrimary = mValues.containsKey(Data.IS_SUPER_PRIMARY); - boolean containsIsPrimary = mValues.containsKey(Data.IS_PRIMARY); - - // Remove primary or super primary values being set to 0. This is disallowed by the - // content provider. - if (containsIsSuperPrimary && mValues.getAsInteger(Data.IS_SUPER_PRIMARY) == 0) { - containsIsSuperPrimary = false; - mValues.remove(Data.IS_SUPER_PRIMARY); - } - if (containsIsPrimary && mValues.getAsInteger(Data.IS_PRIMARY) == 0) { - containsIsPrimary = false; - mValues.remove(Data.IS_PRIMARY); - } - if (!callerIsSyncAdapter) { selection = DatabaseUtils.concatenateWhere(selection, Data.IS_READ_ONLY + "=0"); @@ -6153,7 +6218,8 @@ public class ContactsProvider2 extends SQLiteContentProvider implements OnAccoun * Sets the given dataId record in the "data" table to primary, and resets all data records of * the same mimetype and under the same contact to not be primary. * - * @param dataId the id of the data record to be set to primary. + * @param dataId the id of the data record to be set to primary. Pass -1 to clear the primary + * flag of all data items of this raw contacts */ private void setIsPrimary(long rawContactId, long dataId, long mimeTypeId) { mSetPrimaryStatement.bindLong(1, dataId); @@ -6175,6 +6241,35 @@ public class ContactsProvider2 extends SQLiteContentProvider implements OnAccoun mSetSuperPrimaryStatement.execute(); } + /** + * Performs a query and returns true if any Data item of the raw contact with the given + * id and mimetype is marked as super-primary + */ + private boolean rawContactHasSuperPrimary(long rawContactId, long mimeTypeId) { + final Cursor existsCursor = mDb.rawQuery( + "SELECT EXISTS(SELECT 1 FROM " + Tables.DATA + " WHERE " + + Data.RAW_CONTACT_ID + "=?" + + " AND " + DataColumns.MIMETYPE_ID + "=?" + + " AND " + Data.IS_SUPER_PRIMARY + "<>0)", + new String[] { String.valueOf(rawContactId), String.valueOf(mimeTypeId) }); + try { + if (!existsCursor.moveToFirst()) throw new IllegalStateException(); + return existsCursor.getInt(0) != 0; + } finally { + existsCursor.close(); + } + } + + /* + * Clears the super primary of all data items of the given raw contact. does not touch + * other raw contacts of the same joined aggregate + */ + private void clearSuperPrimary(long rawContactId, long mimeTypeId) { + mClearSuperPrimaryStatement.bindLong(1, mimeTypeId); + mClearSuperPrimaryStatement.bindLong(2, rawContactId); + mClearSuperPrimaryStatement.execute(); + } + public String insertNameLookupForEmail(long rawContactId, long dataId, String email) { if (TextUtils.isEmpty(email)) { return null; diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java index f625a39..9277369 100644 --- a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java +++ b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java @@ -2496,9 +2496,6 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test { " AND " + Data.MIMETYPE + "='testmimetype'", null); assertNetworkNotified(true); - // Should not be able to change IS_PRIMARY and IS_SUPER_PRIMARY by the above update - values.put(Data.IS_PRIMARY, 1); - values.put(Data.IS_SUPER_PRIMARY, 1); assertStoredValues(uri, values); int count = mResolver.delete(Data.CONTENT_URI, Data.RAW_CONTACT_ID + "=" + rawContactId @@ -3005,6 +3002,162 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test { assertStoredValue(contactUri, Contacts.STARRED, "1"); } + public void testSetAndClearSuperPrimaryEmail() { + long rawContactId1 = createRawContact(new Account("a", "a")); + Uri mailUri11 = insertEmail(rawContactId1, "test1@domain1.com"); + Uri mailUri12 = insertEmail(rawContactId1, "test2@domain1.com"); + + long rawContactId2 = createRawContact(new Account("b", "b")); + Uri mailUri21 = insertEmail(rawContactId2, "test1@domain2.com"); + Uri mailUri22 = insertEmail(rawContactId2, "test2@domain2.com"); + + assertStoredValue(mailUri11, Data.IS_PRIMARY, 0); + assertStoredValue(mailUri11, Data.IS_SUPER_PRIMARY, 0); + assertStoredValue(mailUri12, Data.IS_PRIMARY, 0); + assertStoredValue(mailUri12, Data.IS_SUPER_PRIMARY, 0); + assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); + assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); + assertStoredValue(mailUri22, Data.IS_PRIMARY, 0); + assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 0); + + // Set super primary on the first pair, primary on the second + { + ContentValues values = new ContentValues(); + values.put(Data.IS_SUPER_PRIMARY, 1); + mResolver.update(mailUri11, values, null, null); + } + { + ContentValues values = new ContentValues(); + values.put(Data.IS_SUPER_PRIMARY, 1); + mResolver.update(mailUri22, values, null, null); + } + + assertStoredValue(mailUri11, Data.IS_PRIMARY, 1); + assertStoredValue(mailUri11, Data.IS_SUPER_PRIMARY, 1); + assertStoredValue(mailUri12, Data.IS_PRIMARY, 0); + assertStoredValue(mailUri12, Data.IS_SUPER_PRIMARY, 0); + assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); + assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); + assertStoredValue(mailUri22, Data.IS_PRIMARY, 1); + assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 1); + + // Clear primary on the first pair, make sure second is not affected and super_primary is + // also cleared + { + ContentValues values = new ContentValues(); + values.put(Data.IS_PRIMARY, 0); + mResolver.update(mailUri11, values, null, null); + } + + assertStoredValue(mailUri11, Data.IS_PRIMARY, 0); + assertStoredValue(mailUri11, Data.IS_SUPER_PRIMARY, 0); + assertStoredValue(mailUri12, Data.IS_PRIMARY, 0); + assertStoredValue(mailUri12, Data.IS_SUPER_PRIMARY, 0); + assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); + assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); + assertStoredValue(mailUri22, Data.IS_PRIMARY, 1); + assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 1); + + // Ensure that we can only clear super_primary, if we specify the correct data row + { + ContentValues values = new ContentValues(); + values.put(Data.IS_SUPER_PRIMARY, 0); + mResolver.update(mailUri21, values, null, null); + } + + assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); + assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); + assertStoredValue(mailUri22, Data.IS_PRIMARY, 1); + assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 1); + + // Ensure that we can only clear primary, if we specify the correct data row + { + ContentValues values = new ContentValues(); + values.put(Data.IS_PRIMARY, 0); + mResolver.update(mailUri21, values, null, null); + } + + assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); + assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); + assertStoredValue(mailUri22, Data.IS_PRIMARY, 1); + assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 1); + + // Now clear super-primary for real + { + ContentValues values = new ContentValues(); + values.put(Data.IS_SUPER_PRIMARY, 0); + mResolver.update(mailUri22, values, null, null); + } + + assertStoredValue(mailUri11, Data.IS_PRIMARY, 0); + assertStoredValue(mailUri11, Data.IS_SUPER_PRIMARY, 0); + assertStoredValue(mailUri12, Data.IS_PRIMARY, 0); + assertStoredValue(mailUri12, Data.IS_SUPER_PRIMARY, 0); + assertStoredValue(mailUri21, Data.IS_PRIMARY, 0); + assertStoredValue(mailUri21, Data.IS_SUPER_PRIMARY, 0); + assertStoredValue(mailUri22, Data.IS_PRIMARY, 1); + assertStoredValue(mailUri22, Data.IS_SUPER_PRIMARY, 0); + } + + /** + * Common function for the testNewPrimaryIn* functions. Its four configurations + * are each called from its own test + */ + public void testChangingPrimary(boolean inUpdate, boolean withSuperPrimary) { + long rawContactId = createRawContact(new Account("a", "a")); + Uri mailUri1 = insertEmail(rawContactId, "test1@domain1.com", true); + + if (withSuperPrimary) { + final ContentValues values = new ContentValues(); + values.put(Data.IS_SUPER_PRIMARY, 1); + mResolver.update(mailUri1, values, null, null); + } + + assertStoredValue(mailUri1, Data.IS_PRIMARY, 1); + assertStoredValue(mailUri1, Data.IS_SUPER_PRIMARY, withSuperPrimary ? 1 : 0); + + // Insert another item + final Uri mailUri2; + if (inUpdate) { + mailUri2 = insertEmail(rawContactId, "test2@domain1.com"); + + assertStoredValue(mailUri1, Data.IS_PRIMARY, 1); + assertStoredValue(mailUri1, Data.IS_SUPER_PRIMARY, withSuperPrimary ? 1 : 0); + assertStoredValue(mailUri2, Data.IS_PRIMARY, 0); + assertStoredValue(mailUri2, Data.IS_SUPER_PRIMARY, 0); + + final ContentValues values = new ContentValues(); + values.put(Data.IS_PRIMARY, 1); + mResolver.update(mailUri2, values, null, null); + } else { + // directly add as default + mailUri2 = insertEmail(rawContactId, "test2@domain1.com", true); + } + + // Ensure that primary has been unset on the first + // If withSuperPrimary is set, also ensure that is has been moved to the new item + assertStoredValue(mailUri1, Data.IS_PRIMARY, 0); + assertStoredValue(mailUri1, Data.IS_SUPER_PRIMARY, 0); + assertStoredValue(mailUri2, Data.IS_PRIMARY, 1); + assertStoredValue(mailUri2, Data.IS_SUPER_PRIMARY, withSuperPrimary ? 1 : 0); + } + + public void testNewPrimaryInInsert() { + testChangingPrimary(false, false); + } + + public void testNewPrimaryInInsertWithSuperPrimary() { + testChangingPrimary(false, true); + } + + public void testNewPrimaryInUpdate() { + testChangingPrimary(true, false); + } + + public void testNewPrimaryInUpdateWithSuperPrimary() { + testChangingPrimary(true, true); + } + public void testLiveFolders() { long rawContactId1 = createRawContactWithName("James", "Sullivan"); insertPhoneNumber(rawContactId1, "5234567890"); |