Fix collation/indexing for i18n contacts
Fix issue of contacts appearing under wrong label--sort contacts by
sort key, not by label.
Fix handling of labels that require more than the first character
(eg Czech 'CH') by using entire sortkey--not just the first letter--
to determine label.
Bug:7351596
Change-Id: Iaabc63041540f621220d0463df3e0850684caa94
diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java
index 1c4c1f3..46039cf 100644
--- a/src/com/android/providers/contacts/ContactsProvider2.java
+++ b/src/com/android/providers/contacts/ContactsProvider2.java
@@ -6136,26 +6136,24 @@
}
private static final class AddressBookIndexQuery {
- public static final String LETTER = "letter";
- public static final String TITLE = "title";
+ public static final String NAME = "name";
+ public static final String LABEL = "label";
public static final String COUNT = "count";
public static final String[] COLUMNS = new String[] {
- LETTER, TITLE, COUNT
+ NAME, LABEL, COUNT
};
- public static final int COLUMN_LETTER = 0;
- public static final int COLUMN_TITLE = 1;
+ public static final int COLUMN_NAME = 0;
+ public static final int COLUMN_LABEL = 1;
public static final int COLUMN_COUNT = 2;
- // The first letter of the sort key column is what is used for the index headings.
- public static final String SECTION_HEADING = "SUBSTR(%1$s,1,1)";
-
- public static final String ORDER_BY = LETTER + " COLLATE " + PHONEBOOK_COLLATOR_NAME;
+ // PHONEBOOK collator registered in sqlite3_android.cpp
+ public static final String ORDER_BY = NAME + " COLLATE " + PHONEBOOK_COLLATOR_NAME;
}
/**
- * Computes counts by the address book index titles and returns it as {@link Bundle} which
+ * Computes counts by the address book index labels and returns it as {@link Bundle} which
* will be appended to a {@link Cursor} as extras.
*/
private static Bundle getFastScrollingIndexExtras(final Uri queryUri, final SQLiteDatabase db,
@@ -6181,10 +6179,8 @@
}
HashMap<String, String> projectionMap = Maps.newHashMap();
- String sectionHeading = String.format(Locale.US, AddressBookIndexQuery.SECTION_HEADING,
- sortKey);
- projectionMap.put(AddressBookIndexQuery.LETTER,
- sectionHeading + " AS " + AddressBookIndexQuery.LETTER);
+ projectionMap.put(AddressBookIndexQuery.NAME,
+ sortKey + " AS " + AddressBookIndexQuery.NAME);
// If "what to count" is not specified, we just count all records.
if (TextUtils.isEmpty(countExpression)) {
@@ -6193,14 +6189,14 @@
/**
* Use the GET_PHONEBOOK_INDEX function, which is an android extension for SQLite3,
- * to map the first letter of the sort key to a character that is traditionally
- * used in phonebooks to represent that letter. For example, in Korean it will
- * be the first consonant in the letter; for Japanese it will be Hiragana rather
- * than Katakana.
+ * to map the sort key to a character that is traditionally used in phonebooks to
+ * label its section. For example, in Korean it will be the first consonant in the
+ * letter; for Japanese it will be Hiragana rather than Katakana. Note the label may
+ * be more than one character in some languages, such as "CH" in Czech.
*/
- projectionMap.put(AddressBookIndexQuery.TITLE,
- "GET_PHONEBOOK_INDEX(" + sectionHeading + ",'" + currentLocale.toString() + "')"
- + " AS " + AddressBookIndexQuery.TITLE);
+ projectionMap.put(AddressBookIndexQuery.LABEL,
+ "GET_PHONEBOOK_INDEX(" + sortKey + ",'" + currentLocale.toString() + "')"
+ + " AS " + AddressBookIndexQuery.LABEL);
projectionMap.put(AddressBookIndexQuery.COUNT,
"COUNT(" + countExpression + ") AS " + AddressBookIndexQuery.COUNT);
qb.setProjectionMap(projectionMap);
@@ -6212,23 +6208,23 @@
try {
int groupCount = indexCursor.getCount();
- String titles[] = new String[groupCount];
+ String labels[] = new String[groupCount];
int counts[] = new int[groupCount];
int indexCount = 0;
- String currentTitle = null;
+ String currentLabel = null;
// Since GET_PHONEBOOK_INDEX is a many-to-1 function, we may end up
- // with multiple entries for the same title. The following code
+ // with multiple entries for the same label. The following code
// collapses those duplicates.
for (int i = 0; i < groupCount; i++) {
indexCursor.moveToNext();
- String title = indexCursor.getString(AddressBookIndexQuery.COLUMN_TITLE);
- if (title == null) {
- title = "";
+ String label = indexCursor.getString(AddressBookIndexQuery.COLUMN_LABEL);
+ if (label == null) {
+ label = "";
}
int count = indexCursor.getInt(AddressBookIndexQuery.COLUMN_COUNT);
- if (indexCount == 0 || !TextUtils.equals(title, currentTitle)) {
- titles[indexCount] = currentTitle = title;
+ if (indexCount == 0 || !TextUtils.equals(label, currentLabel)) {
+ labels[indexCount] = currentLabel = label;
counts[indexCount] = count;
indexCount++;
} else {
@@ -6237,15 +6233,15 @@
}
if (indexCount < groupCount) {
- String[] newTitles = new String[indexCount];
- System.arraycopy(titles, 0, newTitles, 0, indexCount);
- titles = newTitles;
+ String[] newLabels = new String[indexCount];
+ System.arraycopy(labels, 0, newLabels, 0, indexCount);
+ labels = newLabels;
int[] newCounts = new int[indexCount];
System.arraycopy(counts, 0, newCounts, 0, indexCount);
counts = newCounts;
}
- return FastScrollingIndexCache.buildExtraBundle(titles, counts);
+ return FastScrollingIndexCache.buildExtraBundle(labels, counts);
} finally {
indexCursor.close();
}