summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Lehmann <lehmannd@google.com>2010-11-23 17:37:18 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2010-11-23 17:37:18 -0800
commitfdcf0d5bef479819f9715c0bc750d1e8fa0dcd3e (patch)
treea1216358abeb976c1f5094fa36e8cb0e845bf278
parent359c52a6988dd3e2db2327ec36e5870906fbf359 (diff)
parent6dd371aea88e09cbe56b8c483021f3bf61527331 (diff)
downloadpackages_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.java159
-rw-r--r--tests/src/com/android/providers/contacts/ContactsProvider2Test.java159
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");