Fix malfunctioning bucketization logic
I82052953d5dad42ac171df29248ed25e9b4a2434 dropped the
logic so we need to re-introduce it correctly
As we don't have public API for updating LAST_TIME_USED
columns outside the provider, we need to let the unit test
call a method in ContactsProvider2 directly instead of
calling DataUsageStat API.
- fix the query
- make update logic package-private
- add a unit test for it
- introduce guava to include @VisibleForTesting
Bug: 4998821
Change-Id: I0b699bffffd42a13ab00ac335796687052efb67a
diff --git a/Android.mk b/Android.mk
index e3f60fc..634ef9f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -10,7 +10,7 @@
LOCAL_JAVA_LIBRARIES := ext
-LOCAL_STATIC_JAVA_LIBRARIES += android-common com.android.vcard
+LOCAL_STATIC_JAVA_LIBRARIES += android-common com.android.vcard guava
# The Emma tool analyzes code coverage when running unit tests on the
# application. This configuration line selects which packages will be analyzed,
diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java
index fa58025..6bbbfef 100644
--- a/src/com/android/providers/contacts/ContactsProvider2.java
+++ b/src/com/android/providers/contacts/ContactsProvider2.java
@@ -49,6 +49,7 @@
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
import com.google.android.collect.Sets;
+import com.google.common.annotations.VisibleForTesting;
import android.accounts.Account;
import android.accounts.AccountManager;
@@ -460,6 +461,9 @@
// Recent contacts - those contacted within the last 30 days (in seconds)
private static final long EMAIL_FILTER_RECENT = 30 * 24 * 60 * 60;
+ private static final String TIME_SINCE_LAST_USED =
+ "(strftime('%s', 'now') - " + DataUsageStatColumns.LAST_TIME_USED + "/1000)";
+
/*
* Sorting order for email address suggestions: first starred, then the rest.
* second in_visible_group, then the rest.
@@ -472,9 +476,9 @@
private static final String EMAIL_FILTER_SORT_ORDER =
Contacts.STARRED + " DESC, "
+ Contacts.IN_VISIBLE_GROUP + " DESC, "
- + "(CASE WHEN " + DataUsageStatColumns.LAST_TIME_USED + " < " + EMAIL_FILTER_CURRENT
+ + "(CASE WHEN " + TIME_SINCE_LAST_USED + " < " + EMAIL_FILTER_CURRENT
+ " THEN 0 "
- + " WHEN " + DataUsageStatColumns.LAST_TIME_USED + " < " + EMAIL_FILTER_RECENT
+ + " WHEN " + TIME_SINCE_LAST_USED + " < " + EMAIL_FILTER_RECENT
+ " THEN 1 "
+ " ELSE 2 END), "
+ DataUsageStatColumns.TIMES_USED + " DESC, "
@@ -6863,8 +6867,9 @@
*
* @return the number of rows affected.
*/
- private int updateDataUsageStat(
- ArrayList<Long> dataIds, String type, long currentTimeMillis) {
+ @VisibleForTesting
+ /* package */ int updateDataUsageStat(
+ List<Long> dataIds, String type, long currentTimeMillis) {
final int typeInt = sDataUsageTypeMap.get(type);
final String where = DataUsageStatColumns.DATA_ID + " =? AND "
+ DataUsageStatColumns.USAGE_TYPE_INT + " =?";
diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
index cdbf761..597b975 100644
--- a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
@@ -18,6 +18,7 @@
import com.android.internal.util.ArrayUtils;
import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.DataUsageStatColumns;
import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
import com.android.providers.contacts.tests.R;
import com.google.android.collect.Lists;
@@ -31,6 +32,7 @@
import android.content.EntityIterator;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.AggregationExceptions;
@@ -1244,6 +1246,71 @@
assertStoredValuesOrderly(filterUri3, new ContentValues[] { v3, v1, v2 });
}
+ /**
+ * Tests {@link DataUsageFeedback} correctly bucketize contacts using each
+ * {@link DataUsageStatColumns#LAST_TIME_USED}
+ */
+ public void testEmailFilterSortOrderWithOldHistory() {
+ long rawContactId1 = createRawContact();
+ long dataId1 = ContentUris.parseId(insertEmail(rawContactId1, "address1@email.com"));
+ long dataId2 = ContentUris.parseId(insertEmail(rawContactId1, "address2@email.com"));
+ long dataId3 = ContentUris.parseId(insertEmail(rawContactId1, "address3@email.com"));
+ long dataId4 = ContentUris.parseId(insertEmail(rawContactId1, "address4@email.com"));
+
+ Uri filterUri1 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "address");
+
+ ContentValues v1 = new ContentValues();
+ v1.put(Email.ADDRESS, "address1@email.com");
+ ContentValues v2 = new ContentValues();
+ v2.put(Email.ADDRESS, "address2@email.com");
+ ContentValues v3 = new ContentValues();
+ v3.put(Email.ADDRESS, "address3@email.com");
+ ContentValues v4 = new ContentValues();
+ v4.put(Email.ADDRESS, "address4@email.com");
+
+ final ContactsProvider2 provider = (ContactsProvider2) getProvider();
+
+ long nowInMillis = System.currentTimeMillis();
+ long yesterdayInMillis = (nowInMillis - 24 * 60 * 60 * 1000);
+ long sevenDaysAgoInMillis = (nowInMillis - 7 * 24 * 60 * 60 * 1000);
+ long oneYearAgoInMillis = (nowInMillis - 365L * 24 * 60 * 60 * 1000);
+
+ // address4 is contacted just once yesterday.
+ provider.updateDataUsageStat(Arrays.asList(dataId4),
+ DataUsageFeedback.USAGE_TYPE_LONG_TEXT, yesterdayInMillis);
+
+ // address3 is contacted twice 1 week ago.
+ provider.updateDataUsageStat(Arrays.asList(dataId3),
+ DataUsageFeedback.USAGE_TYPE_LONG_TEXT, sevenDaysAgoInMillis);
+ provider.updateDataUsageStat(Arrays.asList(dataId3),
+ DataUsageFeedback.USAGE_TYPE_LONG_TEXT, sevenDaysAgoInMillis);
+
+ // address2 is contacted three times 1 year ago.
+ provider.updateDataUsageStat(Arrays.asList(dataId2),
+ DataUsageFeedback.USAGE_TYPE_LONG_TEXT, oneYearAgoInMillis);
+ provider.updateDataUsageStat(Arrays.asList(dataId2),
+ DataUsageFeedback.USAGE_TYPE_LONG_TEXT, oneYearAgoInMillis);
+ provider.updateDataUsageStat(Arrays.asList(dataId2),
+ DataUsageFeedback.USAGE_TYPE_LONG_TEXT, oneYearAgoInMillis);
+
+ // auto-complete should prefer recently contacted methods
+ assertStoredValuesOrderly(filterUri1, new ContentValues[] { v4, v3, v2, v1 });
+
+ // Pretend address2 is contacted right now
+ provider.updateDataUsageStat(Arrays.asList(dataId2),
+ DataUsageFeedback.USAGE_TYPE_LONG_TEXT, nowInMillis);
+
+ // Now address2 is the most recently used address
+ assertStoredValuesOrderly(filterUri1, new ContentValues[] { v2, v4, v3, v1 });
+
+ // Pretend address1 is contacted right now
+ provider.updateDataUsageStat(Arrays.asList(dataId1),
+ DataUsageFeedback.USAGE_TYPE_LONG_TEXT, nowInMillis);
+
+ // address2 is preferred to address1 as address2 is used 4 times in total
+ assertStoredValuesOrderly(filterUri1, new ContentValues[] { v2, v1, v4, v3 });
+ }
+
public void testPostalsQuery() {
long rawContactId = createRawContactWithName("Alice", "Nextore");
Uri dataUri = insertPostalAddress(rawContactId, "1600 Amphiteatre Ave, Mountain View");