Loading core/java/com/android/internal/inputmethod/InputMethodUtils.java +39 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,9 @@ import android.os.RemoteException; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.text.TextUtils; import android.text.TextUtils.SimpleStringSplitter; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Pair; import android.util.Slog; import android.view.inputmethod.InputMethodInfo; Loading Loading @@ -61,6 +64,8 @@ public class InputMethodUtils { private static final String TAG_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE = "EnabledWhenDefaultIsNotAsciiCapable"; private static final String TAG_ASCII_CAPABLE = "AsciiCapable"; private static final char INPUT_METHOD_SEPARATOR = ':'; private static final char INPUT_METHOD_SUBTYPE_SEPARATOR = ';'; /** * Used in {@link #getFallbackLocaleForDefaultIme(ArrayList, Context)} to find the fallback IMEs * that are mainly used until the system becomes ready. Note that {@link Locale} in this array Loading Loading @@ -765,6 +770,40 @@ public class InputMethodUtils { } } /** * Parses the setting stored input methods and subtypes string value. * * @param inputMethodsAndSubtypesString The input method subtypes value stored in settings. * @return Map from input method ID to set of input method subtypes IDs. */ @VisibleForTesting public static ArrayMap<String, ArraySet<String>> parseInputMethodsAndSubtypesString( @Nullable final String inputMethodsAndSubtypesString) { final ArrayMap<String, ArraySet<String>> imeMap = new ArrayMap<String, ArraySet<String>>(); if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) { return imeMap; } final SimpleStringSplitter typeSplitter = new SimpleStringSplitter(INPUT_METHOD_SEPARATOR); final SimpleStringSplitter subtypeSplitter = new SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATOR); List<Pair<String, ArrayList<String>>> allImeSettings = InputMethodSettings.buildInputMethodsAndSubtypeList(inputMethodsAndSubtypesString, typeSplitter, subtypeSplitter); for (Pair<String, ArrayList<String>> ime : allImeSettings) { ArraySet<String> subtypes = new ArraySet<String>(); if (ime.second != null) { subtypes.addAll(ime.second); } imeMap.put(ime.first, subtypes); } return imeMap; } /** * Utility class for putting and getting settings for InputMethod * TODO: Move all putters and getters of settings to this class. Loading core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java +128 −1 Original line number Diff line number Diff line Loading @@ -23,9 +23,11 @@ import android.content.pm.ServiceInfo; import android.os.Parcel; import android.test.InstrumentationTestCase; import android.test.suitebuilder.annotation.SmallTest; import android.util.ArrayMap; import android.util.ArraySet; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; import android.view.inputmethod.InputMethodSubtype; import java.util.ArrayList; import java.util.List; Loading Loading @@ -947,4 +949,129 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { assertEquals(Locale.ENGLISH, locales.get(4)); } } public void testParseInputMethodsAndSubtypesString() { // Trivial cases. { assertTrue(InputMethodUtils.parseInputMethodsAndSubtypesString("").isEmpty()); assertTrue(InputMethodUtils.parseInputMethodsAndSubtypesString(null).isEmpty()); } // No subtype cases. { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0"); assertEquals(1, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.get("ime0").isEmpty()); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0:ime1"); assertEquals(2, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.get("ime0").isEmpty()); assertTrue(r.containsKey("ime1")); assertTrue(r.get("ime1").isEmpty()); } // Input metho IDs and their subtypes. { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0;subtype0"); assertEquals(1, r.size()); assertTrue(r.containsKey("ime0")); ArraySet<String> subtypes = r.get("ime0"); assertEquals(1, subtypes.size()); assertTrue(subtypes.contains("subtype0")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0;subtype0;subtype0"); assertEquals(1, r.size()); assertTrue(r.containsKey("ime0")); ArraySet<String> subtypes = r.get("ime0"); assertEquals(1, subtypes.size()); assertTrue(subtypes.contains("subtype0")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0;subtype0;subtype1"); assertEquals(1, r.size()); assertTrue(r.containsKey("ime0")); ArraySet<String> subtypes = r.get("ime0"); assertEquals(2, subtypes.size()); assertTrue(subtypes.contains("subtype0")); assertTrue(subtypes.contains("subtype1")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString( "ime0;subtype0:ime1;subtype1"); assertEquals(2, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.containsKey("ime1")); ArraySet<String> subtypes0 = r.get("ime0"); assertEquals(1, subtypes0.size()); assertTrue(subtypes0.contains("subtype0")); ArraySet<String> subtypes1 = r.get("ime1"); assertEquals(1, subtypes1.size()); assertTrue(subtypes1.contains("subtype1")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype2"); assertEquals(2, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.containsKey("ime1")); ArraySet<String> subtypes0 = r.get("ime0"); assertEquals(2, subtypes0.size()); assertTrue(subtypes0.contains("subtype0")); assertTrue(subtypes0.contains("subtype1")); ArraySet<String> subtypes1 = r.get("ime1"); assertEquals(1, subtypes1.size()); assertTrue(subtypes1.contains("subtype2")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype1;subtype2"); assertEquals(2, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.containsKey("ime1")); ArraySet<String> subtypes0 = r.get("ime0"); assertEquals(2, subtypes0.size()); assertTrue(subtypes0.contains("subtype0")); assertTrue(subtypes0.contains("subtype1")); ArraySet<String> subtypes1 = r.get("ime1"); assertEquals(2, subtypes1.size()); assertTrue(subtypes0.contains("subtype1")); assertTrue(subtypes1.contains("subtype2")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype1;subtype2:ime2"); assertEquals(3, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.containsKey("ime1")); assertTrue(r.containsKey("ime2")); ArraySet<String> subtypes0 = r.get("ime0"); assertEquals(2, subtypes0.size()); assertTrue(subtypes0.contains("subtype0")); assertTrue(subtypes0.contains("subtype1")); ArraySet<String> subtypes1 = r.get("ime1"); assertEquals(2, subtypes1.size()); assertTrue(subtypes0.contains("subtype1")); assertTrue(subtypes1.contains("subtype2")); ArraySet<String> subtypes2 = r.get("ime2"); assertTrue(subtypes2.isEmpty()); } } } services/core/java/com/android/server/InputMethodManagerService.java +4 −31 Original line number Diff line number Diff line Loading @@ -145,9 +145,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub static final boolean DEBUG_RESTORE = DEBUG || false; static final String TAG = "InputMethodManagerService"; private static final char INPUT_METHOD_SEPARATOR = ':'; private static final char INPUT_METHOD_SUBTYPE_SEPARATOR = ';'; static final int MSG_SHOW_IM_SUBTYPE_PICKER = 1; static final int MSG_SHOW_IM_SUBTYPE_ENABLER = 2; static final int MSG_SHOW_IM_CONFIG = 3; Loading Loading @@ -528,8 +525,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub Slog.i(TAG, " new=" + newValue); } // 'new' is the just-restored state, 'prev' is what was in settings prior to the restore ArrayMap<String, ArraySet<String>> prevMap = parseInputMethodsAndSubtypesString(prevValue); ArrayMap<String, ArraySet<String>> newMap = parseInputMethodsAndSubtypesString(newValue); ArrayMap<String, ArraySet<String>> prevMap = InputMethodUtils.parseInputMethodsAndSubtypesString(prevValue); ArrayMap<String, ArraySet<String>> newMap = InputMethodUtils.parseInputMethodsAndSubtypesString(newValue); // Merge the restored ime+subtype enabled states into the live state for (ArrayMap.Entry<String, ArraySet<String>> entry : newMap.entrySet()) { Loading Loading @@ -568,32 +567,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return InputMethodSettings.buildInputMethodsSettingString(imeMap); } // TODO: Move this method to InputMethodUtils with adding unit tests. static ArrayMap<String, ArraySet<String>> parseInputMethodsAndSubtypesString( final String inputMethodsAndSubtypesString) { final ArrayMap<String, ArraySet<String>> imeMap = new ArrayMap<>(); if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) { return imeMap; } final SimpleStringSplitter typeSplitter = new SimpleStringSplitter(INPUT_METHOD_SEPARATOR); final SimpleStringSplitter subtypeSplitter = new SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATOR); List<Pair<String, ArrayList<String>>> allImeSettings = InputMethodSettings.buildInputMethodsAndSubtypeList(inputMethodsAndSubtypesString, typeSplitter, subtypeSplitter); for (Pair<String, ArrayList<String>> ime : allImeSettings) { ArraySet<String> subtypes = new ArraySet<>(); if (ime.second != null) { subtypes.addAll(ime.second); } imeMap.put(ime.first, subtypes); } return imeMap; } class MyPackageMonitor extends PackageMonitor { private boolean isChangingPackagesOfCurrentUser() { final int userId = getChangingUserId(); Loading Loading
core/java/com/android/internal/inputmethod/InputMethodUtils.java +39 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,9 @@ import android.os.RemoteException; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.text.TextUtils; import android.text.TextUtils.SimpleStringSplitter; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Pair; import android.util.Slog; import android.view.inputmethod.InputMethodInfo; Loading Loading @@ -61,6 +64,8 @@ public class InputMethodUtils { private static final String TAG_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE = "EnabledWhenDefaultIsNotAsciiCapable"; private static final String TAG_ASCII_CAPABLE = "AsciiCapable"; private static final char INPUT_METHOD_SEPARATOR = ':'; private static final char INPUT_METHOD_SUBTYPE_SEPARATOR = ';'; /** * Used in {@link #getFallbackLocaleForDefaultIme(ArrayList, Context)} to find the fallback IMEs * that are mainly used until the system becomes ready. Note that {@link Locale} in this array Loading Loading @@ -765,6 +770,40 @@ public class InputMethodUtils { } } /** * Parses the setting stored input methods and subtypes string value. * * @param inputMethodsAndSubtypesString The input method subtypes value stored in settings. * @return Map from input method ID to set of input method subtypes IDs. */ @VisibleForTesting public static ArrayMap<String, ArraySet<String>> parseInputMethodsAndSubtypesString( @Nullable final String inputMethodsAndSubtypesString) { final ArrayMap<String, ArraySet<String>> imeMap = new ArrayMap<String, ArraySet<String>>(); if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) { return imeMap; } final SimpleStringSplitter typeSplitter = new SimpleStringSplitter(INPUT_METHOD_SEPARATOR); final SimpleStringSplitter subtypeSplitter = new SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATOR); List<Pair<String, ArrayList<String>>> allImeSettings = InputMethodSettings.buildInputMethodsAndSubtypeList(inputMethodsAndSubtypesString, typeSplitter, subtypeSplitter); for (Pair<String, ArrayList<String>> ime : allImeSettings) { ArraySet<String> subtypes = new ArraySet<String>(); if (ime.second != null) { subtypes.addAll(ime.second); } imeMap.put(ime.first, subtypes); } return imeMap; } /** * Utility class for putting and getting settings for InputMethod * TODO: Move all putters and getters of settings to this class. Loading
core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java +128 −1 Original line number Diff line number Diff line Loading @@ -23,9 +23,11 @@ import android.content.pm.ServiceInfo; import android.os.Parcel; import android.test.InstrumentationTestCase; import android.test.suitebuilder.annotation.SmallTest; import android.util.ArrayMap; import android.util.ArraySet; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; import android.view.inputmethod.InputMethodSubtype; import java.util.ArrayList; import java.util.List; Loading Loading @@ -947,4 +949,129 @@ public class InputMethodUtilsTest extends InstrumentationTestCase { assertEquals(Locale.ENGLISH, locales.get(4)); } } public void testParseInputMethodsAndSubtypesString() { // Trivial cases. { assertTrue(InputMethodUtils.parseInputMethodsAndSubtypesString("").isEmpty()); assertTrue(InputMethodUtils.parseInputMethodsAndSubtypesString(null).isEmpty()); } // No subtype cases. { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0"); assertEquals(1, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.get("ime0").isEmpty()); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0:ime1"); assertEquals(2, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.get("ime0").isEmpty()); assertTrue(r.containsKey("ime1")); assertTrue(r.get("ime1").isEmpty()); } // Input metho IDs and their subtypes. { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0;subtype0"); assertEquals(1, r.size()); assertTrue(r.containsKey("ime0")); ArraySet<String> subtypes = r.get("ime0"); assertEquals(1, subtypes.size()); assertTrue(subtypes.contains("subtype0")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0;subtype0;subtype0"); assertEquals(1, r.size()); assertTrue(r.containsKey("ime0")); ArraySet<String> subtypes = r.get("ime0"); assertEquals(1, subtypes.size()); assertTrue(subtypes.contains("subtype0")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0;subtype0;subtype1"); assertEquals(1, r.size()); assertTrue(r.containsKey("ime0")); ArraySet<String> subtypes = r.get("ime0"); assertEquals(2, subtypes.size()); assertTrue(subtypes.contains("subtype0")); assertTrue(subtypes.contains("subtype1")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString( "ime0;subtype0:ime1;subtype1"); assertEquals(2, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.containsKey("ime1")); ArraySet<String> subtypes0 = r.get("ime0"); assertEquals(1, subtypes0.size()); assertTrue(subtypes0.contains("subtype0")); ArraySet<String> subtypes1 = r.get("ime1"); assertEquals(1, subtypes1.size()); assertTrue(subtypes1.contains("subtype1")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype2"); assertEquals(2, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.containsKey("ime1")); ArraySet<String> subtypes0 = r.get("ime0"); assertEquals(2, subtypes0.size()); assertTrue(subtypes0.contains("subtype0")); assertTrue(subtypes0.contains("subtype1")); ArraySet<String> subtypes1 = r.get("ime1"); assertEquals(1, subtypes1.size()); assertTrue(subtypes1.contains("subtype2")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype1;subtype2"); assertEquals(2, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.containsKey("ime1")); ArraySet<String> subtypes0 = r.get("ime0"); assertEquals(2, subtypes0.size()); assertTrue(subtypes0.contains("subtype0")); assertTrue(subtypes0.contains("subtype1")); ArraySet<String> subtypes1 = r.get("ime1"); assertEquals(2, subtypes1.size()); assertTrue(subtypes0.contains("subtype1")); assertTrue(subtypes1.contains("subtype2")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype1;subtype2:ime2"); assertEquals(3, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.containsKey("ime1")); assertTrue(r.containsKey("ime2")); ArraySet<String> subtypes0 = r.get("ime0"); assertEquals(2, subtypes0.size()); assertTrue(subtypes0.contains("subtype0")); assertTrue(subtypes0.contains("subtype1")); ArraySet<String> subtypes1 = r.get("ime1"); assertEquals(2, subtypes1.size()); assertTrue(subtypes0.contains("subtype1")); assertTrue(subtypes1.contains("subtype2")); ArraySet<String> subtypes2 = r.get("ime2"); assertTrue(subtypes2.isEmpty()); } } }
services/core/java/com/android/server/InputMethodManagerService.java +4 −31 Original line number Diff line number Diff line Loading @@ -145,9 +145,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub static final boolean DEBUG_RESTORE = DEBUG || false; static final String TAG = "InputMethodManagerService"; private static final char INPUT_METHOD_SEPARATOR = ':'; private static final char INPUT_METHOD_SUBTYPE_SEPARATOR = ';'; static final int MSG_SHOW_IM_SUBTYPE_PICKER = 1; static final int MSG_SHOW_IM_SUBTYPE_ENABLER = 2; static final int MSG_SHOW_IM_CONFIG = 3; Loading Loading @@ -528,8 +525,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub Slog.i(TAG, " new=" + newValue); } // 'new' is the just-restored state, 'prev' is what was in settings prior to the restore ArrayMap<String, ArraySet<String>> prevMap = parseInputMethodsAndSubtypesString(prevValue); ArrayMap<String, ArraySet<String>> newMap = parseInputMethodsAndSubtypesString(newValue); ArrayMap<String, ArraySet<String>> prevMap = InputMethodUtils.parseInputMethodsAndSubtypesString(prevValue); ArrayMap<String, ArraySet<String>> newMap = InputMethodUtils.parseInputMethodsAndSubtypesString(newValue); // Merge the restored ime+subtype enabled states into the live state for (ArrayMap.Entry<String, ArraySet<String>> entry : newMap.entrySet()) { Loading Loading @@ -568,32 +567,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return InputMethodSettings.buildInputMethodsSettingString(imeMap); } // TODO: Move this method to InputMethodUtils with adding unit tests. static ArrayMap<String, ArraySet<String>> parseInputMethodsAndSubtypesString( final String inputMethodsAndSubtypesString) { final ArrayMap<String, ArraySet<String>> imeMap = new ArrayMap<>(); if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) { return imeMap; } final SimpleStringSplitter typeSplitter = new SimpleStringSplitter(INPUT_METHOD_SEPARATOR); final SimpleStringSplitter subtypeSplitter = new SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATOR); List<Pair<String, ArrayList<String>>> allImeSettings = InputMethodSettings.buildInputMethodsAndSubtypeList(inputMethodsAndSubtypesString, typeSplitter, subtypeSplitter); for (Pair<String, ArrayList<String>> ime : allImeSettings) { ArraySet<String> subtypes = new ArraySet<>(); if (ime.second != null) { subtypes.addAll(ime.second); } imeMap.put(ime.first, subtypes); } return imeMap; } class MyPackageMonitor extends PackageMonitor { private boolean isChangingPackagesOfCurrentUser() { final int userId = getChangingUserId(); Loading