summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/allapps/search
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2017-07-18 01:22:01 -0700
committerSunny Goyal <sunnygoyal@google.com>2017-07-18 11:23:23 -0700
commit05d2df1678bfba02c2fbc54ce03229f45b0308cd (patch)
tree92bef2d68d4197ef8eb9c8724750887057ddf023 /src/com/android/launcher3/allapps/search
parent751ea1c10e8e2348a9c0d0a22f8b9df3c9416c1f (diff)
downloadandroid_packages_apps_Trebuchet-05d2df1678bfba02c2fbc54ce03229f45b0308cd.tar.gz
android_packages_apps_Trebuchet-05d2df1678bfba02c2fbc54ce03229f45b0308cd.tar.bz2
android_packages_apps_Trebuchet-05d2df1678bfba02c2fbc54ce03229f45b0308cd.zip
Using collator for string matching
This provides a better matching for non-latin characters on N and above Bug: 63763127 Change-Id: I220487d242ff547311ddd13e7af380a7e47eec0e
Diffstat (limited to 'src/com/android/launcher3/allapps/search')
-rw-r--r--src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java57
1 files changed, 53 insertions, 4 deletions
diff --git a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
index 43033024f..21eb3fba0 100644
--- a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
+++ b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
@@ -20,6 +20,7 @@ import android.os.Handler;
import com.android.launcher3.AppInfo;
import com.android.launcher3.util.ComponentKey;
+import java.text.Collator;
import java.util.ArrayList;
import java.util.List;
@@ -61,8 +62,9 @@ public class DefaultAppSearchAlgorithm implements SearchAlgorithm {
// apps that don't match all of the words in the query.
final String queryTextLower = query.toLowerCase();
final ArrayList<ComponentKey> result = new ArrayList<>();
+ StringMatcher matcher = StringMatcher.getInstance();
for (AppInfo info : mApps) {
- if (matches(info, queryTextLower)) {
+ if (matches(info, queryTextLower, matcher)) {
result.add(info.toComponentKey());
}
}
@@ -70,6 +72,10 @@ public class DefaultAppSearchAlgorithm implements SearchAlgorithm {
}
public static boolean matches(AppInfo info, String query) {
+ return matches(info, query, StringMatcher.getInstance());
+ }
+
+ public static boolean matches(AppInfo info, String query, StringMatcher matcher) {
int queryLength = query.length();
String title = info.title.toString();
@@ -90,7 +96,7 @@ public class DefaultAppSearchAlgorithm implements SearchAlgorithm {
nextType = i < (titleLength - 1) ?
Character.getType(title.codePointAt(i + 1)) : Character.UNASSIGNED;
if (isBreak(thisType, lastType, nextType) &&
- title.substring(i, i + queryLength).equalsIgnoreCase(query)) {
+ matcher.matches(query, title.substring(i, i + queryLength))) {
return true;
}
}
@@ -106,6 +112,13 @@ public class DefaultAppSearchAlgorithm implements SearchAlgorithm {
* 4) Any capital character before a small character
*/
private static boolean isBreak(int thisType, int prevType, int nextType) {
+ switch (prevType) {
+ case Character.UNASSIGNED:
+ case Character.SPACE_SEPARATOR:
+ case Character.LINE_SEPARATOR:
+ case Character.PARAGRAPH_SEPARATOR:
+ return true;
+ }
switch (thisType) {
case Character.UPPERCASE_LETTER:
if (nextType == Character.UPPERCASE_LETTER) {
@@ -132,8 +145,44 @@ public class DefaultAppSearchAlgorithm implements SearchAlgorithm {
// Always a break point for a symbol
return true;
default:
- // Always a break point at first character
- return prevType == Character.UNASSIGNED;
+ return false;
+ }
+ }
+
+ public static class StringMatcher {
+
+ private static final char MAX_UNICODE = '\uFFFF';
+
+ private final Collator mCollator;
+
+ StringMatcher() {
+ // On android N and above, Collator uses ICU implementation which has a much better
+ // support for non-latin locales.
+ mCollator = Collator.getInstance();
+ mCollator.setStrength(Collator.PRIMARY);
+ mCollator.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
+ }
+
+ /**
+ * Returns true if {@param query} is a prefix of {@param target}
+ */
+ public boolean matches(String query, String target) {
+ switch (mCollator.compare(query, target)) {
+ case 0:
+ return true;
+ case -1:
+ // The target string can contain a modifier which would make it larger than
+ // the query string (even though the length is same). If the query becomes
+ // larger after appending a unicode character, it was originally a prefix of
+ // the target string and hence should match.
+ return mCollator.compare(query + MAX_UNICODE, target) > -1;
+ default:
+ return false;
+ }
+ }
+
+ public static StringMatcher getInstance() {
+ return new StringMatcher();
}
}
}