Fix the sort order of the input methods & subtypes in the settings.

It should have been the same as how the IME switcher panel does.

bug: 3364167
Change-Id: I48b98c9c4598720edf7cf09d1b9358a9ebed6051
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
index ce0848b..e9db998 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
@@ -89,14 +89,12 @@
         public int compare(InputMethodInfo imi1, InputMethodInfo imi2) {
             if (imi2 == null) return 0;
             if (imi1 == null) return 1;
-            if (mPackageManager != null) {
-                CharSequence imiId1 = imi1.loadLabel(mPackageManager) + "/" + imi1.getId();
-                CharSequence imiId2 = imi2.loadLabel(mPackageManager) + "/" + imi2.getId();
-                if (imiId1 != null && imiId2 != null) {
-                    return imiId1.toString().compareTo(imiId2.toString());
-                }
+            if (mPackageManager == null) {
+                return imi1.getId().compareTo(imi2.getId());
             }
-            return imi1.getId().compareTo(imi2.getId());
+            CharSequence imiId1 = imi1.loadLabel(mPackageManager) + "/" + imi1.getId();
+            CharSequence imiId2 = imi2.loadLabel(mPackageManager) + "/" + imi2.getId();
+            return imiId1.toString().compareTo(imiId2.toString());
         }
     }
 
@@ -267,7 +265,6 @@
 
         Map<InputMethodInfo, List<InputMethodSubtype>> enabledIMIs =
                 getEnabledInputMethodAndSubtypeList();
-        // TODO: Sort by alphabet and mode.
         Set<InputMethodInfo> cachedImiSet = enabledIMIs.keySet();
         for (InputMethodInfo imi: cachedImiSet) {
             List<InputMethodSubtype> subtypes = enabledIMIs.get(imi);
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index f2cf942..1b47703 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -82,8 +82,8 @@
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.text.Collator;
 import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -1750,10 +1750,28 @@
 
             hideInputMethodMenuLocked();
 
-            final Map<CharSequence, Pair<InputMethodInfo, Integer>> imMap =
-                new TreeMap<CharSequence, Pair<InputMethodInfo, Integer>>(Collator.getInstance());
+            final TreeMap<InputMethodInfo, List<InputMethodSubtype>> sortedImmis =
+                    new TreeMap<InputMethodInfo, List<InputMethodSubtype>>(
+                            new Comparator<InputMethodInfo>() {
+                                @Override
+                                public int compare(InputMethodInfo imi1, InputMethodInfo imi2) {
+                                    if (imi2 == null) return 0;
+                                    if (imi1 == null) return 1;
+                                    if (pm == null) {
+                                        return imi1.getId().compareTo(imi2.getId());
+                                    }
+                                    CharSequence imiId1 = imi1.loadLabel(pm) + "/" + imi1.getId();
+                                    CharSequence imiId2 = imi2.loadLabel(pm) + "/" + imi2.getId();
+                                    return imiId1.toString().compareTo(imiId2.toString());
+                                }
+                            });
 
-            for (InputMethodInfo imi: immis.keySet()) {
+            sortedImmis.putAll(immis);
+
+            final ArrayList<Pair<CharSequence, Pair<InputMethodInfo, Integer>>> imList =
+                    new ArrayList<Pair<CharSequence, Pair<InputMethodInfo, Integer>>>();
+
+            for (InputMethodInfo imi : sortedImmis.keySet()) {
                 if (imi == null) continue;
                 List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypeList = immis.get(imi);
                 HashSet<String> enabledSubtypeSet = new HashSet<String>();
@@ -1767,35 +1785,39 @@
                     for (int j = 0; j < subtypeCount; ++j) {
                         InputMethodSubtype subtype = imi.getSubtypeAt(j);
                         if (enabledSubtypeSet.contains(String.valueOf(subtype.hashCode()))) {
-                            CharSequence title;
+                            final CharSequence title;
                             int nameResId = subtype.getNameResId();
                             String mode = subtype.getMode();
                             if (nameResId != 0) {
                                 title = TextUtils.concat(pm.getText(imi.getPackageName(),
                                         nameResId, imi.getServiceInfo().applicationInfo),
-                                        " (", label, ")");
+                                        (TextUtils.isEmpty(label) ? "" : " (" + label + ")"));
                             } else {
                                 CharSequence language = subtype.getLocale();
                                 // TODO: Use more friendly Title and UI
                                 title = label + "," + (mode == null ? "" : mode) + ","
                                         + (language == null ? "" : language);
                             }
-                            imMap.put(title, new Pair<InputMethodInfo, Integer>(imi, j));
+                            imList.add(new Pair<CharSequence, Pair<InputMethodInfo, Integer>>(
+                                    title, new Pair<InputMethodInfo, Integer>(imi, j)));
                         }
                     }
                 } else {
-                    imMap.put(label,
-                            new Pair<InputMethodInfo, Integer>(imi, NOT_A_SUBTYPE_ID));
+                    imList.add(new Pair<CharSequence, Pair<InputMethodInfo, Integer>>(
+                            label, new Pair<InputMethodInfo, Integer>(imi, NOT_A_SUBTYPE_ID)));
                 }
             }
 
-            final int N = imMap.size();
-            mItems = imMap.keySet().toArray(new CharSequence[N]);
+            final int N = imList.size();
+            mItems = new CharSequence[N];
+            for (int i = 0; i < N; ++i) {
+                mItems[i] = imList.get(i).first;
+            }
             mIms = new InputMethodInfo[N];
             mSubtypeIds = new int[N];
             int checkedItem = 0;
             for (int i = 0; i < N; ++i) {
-                Pair<InputMethodInfo, Integer> value = imMap.get(mItems[i]);
+                Pair<InputMethodInfo, Integer> value = imList.get(i).second;
                 mIms[i] = value.first;
                 mSubtypeIds[i] = value.second;
                 if (mIms[i].getId().equals(lastInputMethodId)) {