diff options
author | Yorke Lee <yorkelee@google.com> | 2013-08-05 15:28:21 -0700 |
---|---|---|
committer | Yorke Lee <yorkelee@google.com> | 2013-08-05 17:07:00 -0700 |
commit | 45b023e89d87b66e44c1b79c6e1444ec9db70a82 (patch) | |
tree | 068a5215c6911e9133bbe7789b3a57799fd8729c | |
parent | a89aa7533a14b143b55bf4a29d284152ab9278a5 (diff) | |
download | ContactsProvider-45b023e89d87b66e44c1b79c6e1444ec9db70a82.tar.gz |
Handle DEMOTE and UNDEMOTE in CP2
* If a contact is UNDEMOTED, if it was previously DEMOTED, it will
become UNPINNED. Otherwise, it will remain unchanged.
* When two raw contacts are aggregated, the parent contact should
inherit the lower pinned position of the two, not including negative
integers.
Change-Id: I74f41dfa327b8e5a79688b1e99eafbef7d9d58a0
3 files changed, 146 insertions, 19 deletions
diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java index 68cb1835..5cdbb198 100644 --- a/src/com/android/providers/contacts/ContactsProvider2.java +++ b/src/com/android/providers/contacts/ContactsProvider2.java @@ -504,6 +504,20 @@ public class ContactsProvider2 extends AbstractContactsProvider " SET " + RawContacts.VERSION + " = " + RawContacts.VERSION + " + 1" + " WHERE " + RawContacts._ID + " IN ("; + /** Sql for undemoting a demoted contact **/ + private static final String UNDEMOTE_CONTACT = + "UPDATE " + Tables.CONTACTS + + " SET " + Contacts.PINNED + " = " + PinnedPositions.UNPINNED + + " WHERE " + Contacts._ID + " = ?1 AND " + Contacts.PINNED + " <= " + + PinnedPositions.DEMOTED; + + /** Sql for undemoting a demoted raw contact **/ + private static final String UNDEMOTE_RAW_CONTACT = + "UPDATE " + Tables.RAW_CONTACTS + + " SET " + RawContacts.PINNED + " = " + PinnedPositions.UNPINNED + + " WHERE " + RawContacts.CONTACT_ID + " = ?1 AND " + Contacts.PINNED + " <= " + + PinnedPositions.DEMOTED; + // Current contacts - those contacted within the last 3 days (in seconds) private static final long LAST_TIME_USED_CURRENT_SEC = 3 * 24 * 60 * 60; @@ -8551,14 +8565,22 @@ public class ContactsProvider2 extends AbstractContactsProvider + id); } + // If contact is to be undemoted, go through a separate un-demotion process + final String undemote = values.getAsString(id); + if (PinnedPositions.UNDEMOTE.equals(undemote)) { + undemoteContact(db, contactId); + continue; + } + final Integer pinnedPosition = values.getAsInteger(id); - if (pinnedPosition == null || pinnedPosition < 0) { - throw new IllegalArgumentException("Pinned position must be a positive integer."); + if (pinnedPosition == null) { + throw new IllegalArgumentException("Pinned position must be an integer."); } args[0] = String.valueOf(contactId); args[1] = String.valueOf(pinnedPosition); if (forceStarWhenPinning) { - args[2] = (pinnedPosition == PinnedPositions.UNPINNED ? "0" : "1"); + args[2] = (pinnedPosition == PinnedPositions.UNPINNED || + pinnedPosition == PinnedPositions.DEMOTED ? "0" : "1"); } db.execSQL(contactSQL, args); @@ -8567,6 +8589,13 @@ public class ContactsProvider2 extends AbstractContactsProvider return count; } + private void undemoteContact(SQLiteDatabase db, long id) { + final String[] arg = new String[1]; + arg[0] = String.valueOf(id); + db.execSQL(UNDEMOTE_CONTACT, arg); + db.execSQL(UNDEMOTE_RAW_CONTACT, arg); + } + private boolean handleDataUsageFeedback(Uri uri) { final long currentTimeMillis = Clock.getInstance().currentTimeMillis(); final String usageType = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); diff --git a/src/com/android/providers/contacts/aggregation/ContactAggregator.java b/src/com/android/providers/contacts/aggregation/ContactAggregator.java index db88c10b..88369f9f 100644 --- a/src/com/android/providers/contacts/aggregation/ContactAggregator.java +++ b/src/com/android/providers/contacts/aggregation/ContactAggregator.java @@ -339,7 +339,8 @@ public class ContactAggregator { mPinnedUpdate = db.compileStatement("UPDATE " + Tables.CONTACTS + " SET " + Contacts.PINNED + "=(SELECT MIN(" + RawContacts.PINNED + ") FROM " + Tables.RAW_CONTACTS + " WHERE " + RawContacts.CONTACT_ID + "=" - + ContactsColumns.CONCRETE_ID + ") WHERE " + Contacts._ID + "=?"); + + ContactsColumns.CONCRETE_ID + " AND " + RawContacts.PINNED + ">" + + PinnedPositions.DEMOTED + ") WHERE " + Contacts._ID + "=?"); mContactIdAndMarkAggregatedUpdate = db.compileStatement( "UPDATE " + Tables.RAW_CONTACTS + @@ -1914,9 +1915,11 @@ public class ContactAggregator { } // contactPinned should be the lowest value of its constituent raw contacts, - // excluding 0 + // excluding negative integers final int rawContactPinned = c.getInt(RawContactsQuery.PINNED); - contactPinned = Math.min(contactPinned, rawContactPinned); + if (rawContactPinned >= 0) { + contactPinned = Math.min(contactPinned, rawContactPinned); + } appendLookupKey( lookupKey, @@ -2366,7 +2369,6 @@ public class ContactAggregator { if (contactId == 0) { return; } - mPinnedUpdate.bindLong(1, contactId); mPinnedUpdate.execute(); } diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java index 3293a5b2..f9b13a58 100644 --- a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java +++ b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java @@ -7885,19 +7885,20 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test { cv(Contacts._ID, i4.mContactId, Contacts.PINNED, PinnedPositions.UNPINNED) ); - // negative number - final ContentValues values = cv(i1.mContactId, 1, i3.mContactId, 3, i4.mContactId, -2); + // Unsupported string + final ContentValues values = cv(i1.mContactId, 1, i3.mContactId, 3, i4.mContactId, + "undemotemeplease!"); try { mResolver.update(ContactsContract.PinnedPositions.UPDATE_URI, values, null, null); - fail("Pinned position must be a distinct(unrepeated) positive integer."); + fail("Pinned position must be an integer."); } catch (IllegalArgumentException expected) { } - // non-integer - final ContentValues values3 = cv(i1.mContactId, "1.1"); + // Float + final ContentValues values2 = cv(i1.mContactId, "1.1"); try { - mResolver.update(ContactsContract.PinnedPositions.UPDATE_URI, values, null, null); - fail("Pinned position must be a distinct(unrepeated) positive integer."); + mResolver.update(ContactsContract.PinnedPositions.UPDATE_URI, values2, null, null); + fail("Pinned position must be an integer"); } catch (IllegalArgumentException expected) { } @@ -7923,8 +7924,11 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test { final DatabaseAsserts.ContactIdPair i2 = DatabaseAsserts.assertAndCreateContact(mResolver); final DatabaseAsserts.ContactIdPair i3 = DatabaseAsserts.assertAndCreateContact(mResolver); final DatabaseAsserts.ContactIdPair i4 = DatabaseAsserts.assertAndCreateContact(mResolver); + final DatabaseAsserts.ContactIdPair i5 = DatabaseAsserts.assertAndCreateContact(mResolver); + final DatabaseAsserts.ContactIdPair i6 = DatabaseAsserts.assertAndCreateContact(mResolver); - final ContentValues values = cv(i1.mContactId, 1, i2.mContactId, 2, i3.mContactId, 3); + final ContentValues values = cv(i1.mContactId, 1, i2.mContactId, 2, i3.mContactId, 3, + i5.mContactId, 5, i6.mContactId, 6); mResolver.update(ContactsContract.PinnedPositions.UPDATE_URI.buildUpon() .appendQueryParameter(PinnedPositions.STAR_WHEN_PINNING, "true").build(), values, null, null); @@ -7937,7 +7941,9 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test { assertStoredValuesWithProjection(Contacts.CONTENT_URI, cv(Contacts._ID, i1.mContactId, Contacts.PINNED, 1), cv(Contacts._ID, i2.mContactId, Contacts.PINNED, 2), - cv(Contacts._ID, i3.mContactId, Contacts.PINNED, 3) + cv(Contacts._ID, i3.mContactId, Contacts.PINNED, 3), + cv(Contacts._ID, i5.mContactId, Contacts.PINNED, 5), + cv(Contacts._ID, i6.mContactId, Contacts.PINNED, 6) ); assertStoredValuesWithProjection(RawContacts.CONTENT_URI, @@ -7948,7 +7954,11 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test { cv(RawContacts._ID, i3.mRawContactId, RawContacts.PINNED, 3, RawContacts.STARRED, 1), cv(RawContacts._ID, i4.mRawContactId, RawContacts.PINNED, PinnedPositions.UNPINNED, - RawContacts.STARRED, 0) + RawContacts.STARRED, 0), + cv(RawContacts._ID, i5.mRawContactId, RawContacts.PINNED, 5, + RawContacts.STARRED, 1), + cv(RawContacts._ID, i6.mRawContactId, RawContacts.PINNED, 6, + RawContacts.STARRED, 1) ); // aggregate raw contact 2 and 3 together. @@ -7959,14 +7969,19 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test { // pinned position assertStoredValuesWithProjection(Contacts.CONTENT_URI, cv(Contacts._ID, i1.mContactId, Contacts.PINNED, 1), - cv(Contacts._ID, i2.mContactId, Contacts.PINNED, 2) + cv(Contacts._ID, i2.mContactId, Contacts.PINNED, 2), + cv(Contacts._ID, i5.mContactId, Contacts.PINNED, 5), + cv(Contacts._ID, i6.mContactId, Contacts.PINNED, 6) ); assertStoredValuesWithProjection(RawContacts.CONTENT_URI, cv(RawContacts._ID, i1.mRawContactId, RawContacts.PINNED, 1), cv(RawContacts._ID, i2.mRawContactId, RawContacts.PINNED, 2), cv(RawContacts._ID, i3.mRawContactId, RawContacts.PINNED, 3), - cv(RawContacts._ID, i4.mRawContactId, RawContacts.PINNED, PinnedPositions.UNPINNED) + cv(RawContacts._ID, i4.mRawContactId, RawContacts.PINNED, + PinnedPositions.UNPINNED), + cv(RawContacts._ID, i5.mRawContactId, RawContacts.PINNED, 5), + cv(RawContacts._ID, i6.mRawContactId, RawContacts.PINNED, 6) ); // split the aggregated raw contacts @@ -7982,6 +7997,87 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test { cv(RawContacts._ID, i3.mRawContactId, RawContacts.PINNED, 3, RawContacts.STARRED, 1), cv(RawContacts._ID, i4.mRawContactId, RawContacts.PINNED, PinnedPositions.UNPINNED, + RawContacts.STARRED, 0), + cv(RawContacts._ID, i5.mRawContactId, RawContacts.PINNED, 5, + RawContacts.STARRED, 1), + cv(RawContacts._ID, i6.mRawContactId, RawContacts.PINNED, 6, + RawContacts.STARRED, 1) + ); + + + + // now demote contact 5 + final ContentValues cv = cv(i5.mContactId, PinnedPositions.DEMOTED); + mResolver.update(ContactsContract.PinnedPositions.UPDATE_URI.buildUpon().build(), + cv, null, null); + + // Get new contact Ids for contacts composing of raw contacts 1 and 4 because they have + // changed. + final long cId1 = RawContactUtil.queryContactIdByRawContactId(mResolver, i1.mRawContactId); + final long cId4 = RawContactUtil.queryContactIdByRawContactId(mResolver, i4.mRawContactId); + + assertStoredValuesWithProjection(Contacts.CONTENT_URI, + cv(Contacts._ID, cId1, Contacts.PINNED, PinnedPositions.UNPINNED), + cv(Contacts._ID, i2.mContactId, Contacts.PINNED, 2), + cv(Contacts._ID, cId4, Contacts.PINNED, PinnedPositions.UNPINNED), + cv(Contacts._ID, i5.mContactId, Contacts.PINNED, PinnedPositions.DEMOTED), + cv(Contacts._ID, i6.mContactId, Contacts.PINNED, 6) + ); + + // aggregate contacts 5 and 6 together + setAggregationException(AggregationExceptions.TYPE_KEEP_TOGETHER, i5.mRawContactId, + i6.mRawContactId); + + // The resulting contact should have a pinned value of 6 + assertStoredValuesWithProjection(Contacts.CONTENT_URI, + cv(Contacts._ID, cId1, Contacts.PINNED, PinnedPositions.UNPINNED), + cv(Contacts._ID, i2.mContactId, Contacts.PINNED, 2), + cv(Contacts._ID, cId4, Contacts.PINNED, PinnedPositions.UNPINNED), + cv(Contacts._ID, i5.mContactId, Contacts.PINNED, 6) + ); + } + + public void testPinnedPositionsAfterDemoteAndUndemote() { + final DatabaseAsserts.ContactIdPair i1 = DatabaseAsserts.assertAndCreateContact(mResolver); + final DatabaseAsserts.ContactIdPair i2 = DatabaseAsserts.assertAndCreateContact(mResolver); + + final ContentValues values = cv(i1.mContactId, 0, i2.mContactId, PinnedPositions.DEMOTED); + + // Pin contact 1 and demote contact 2 + mResolver.update(ContactsContract.PinnedPositions.UPDATE_URI.buildUpon(). + appendQueryParameter(PinnedPositions.STAR_WHEN_PINNING, "true"). + build(), values, null, null); + + assertStoredValuesWithProjection(Contacts.CONTENT_URI, + cv(Contacts._ID, i1.mContactId, Contacts.PINNED, 0, Contacts.STARRED, 1), + cv(Contacts._ID, i2.mContactId, Contacts.PINNED, PinnedPositions.DEMOTED, + Contacts.STARRED, 0) + ); + + assertStoredValuesWithProjection(RawContacts.CONTENT_URI, + cv(RawContacts._ID, i1.mRawContactId, RawContacts.PINNED, 0, + RawContacts.STARRED, 1), + cv(RawContacts._ID, i2.mRawContactId, RawContacts.PINNED, PinnedPositions.DEMOTED, + RawContacts.STARRED, 0) + ); + + // Now undemote both contacts + final ContentValues values2 = cv(i1.mContactId, PinnedPositions.UNDEMOTE, i2.mContactId, + PinnedPositions.UNDEMOTE); + mResolver.update(ContactsContract.PinnedPositions.UPDATE_URI.buildUpon(). + build(), values2, null, null); + + // Contact 1 remains pinned at 0, while contact 2 becomes unpinned + assertStoredValuesWithProjection(Contacts.CONTENT_URI, + cv(Contacts._ID, i1.mContactId, Contacts.PINNED, 0, Contacts.STARRED, 1), + cv(Contacts._ID, i2.mContactId, Contacts.PINNED, PinnedPositions.UNPINNED, + Contacts.STARRED, 0) + ); + + assertStoredValuesWithProjection(RawContacts.CONTENT_URI, + cv(RawContacts._ID, i1.mRawContactId, RawContacts.PINNED, 0, + RawContacts.STARRED, 1), + cv(RawContacts._ID, i2.mRawContactId, RawContacts.PINNED, PinnedPositions.UNPINNED, RawContacts.STARRED, 0) ); } |