OSDN Git Service

Add unit tests for InputMethodSubtypeSwitchingController
authorYohei Yukawa <yukawa@google.com>
Thu, 1 May 2014 08:20:05 +0000 (17:20 +0900)
committerYohei Yukawa <yukawa@google.com>
Thu, 1 May 2014 10:13:25 +0000 (19:13 +0900)
This CL adds unit tests for InputMethodSubtypeSwitchingController
as a ground work to make it aware of
supportsSwitchingToNextInputMethod in a subsequent CL.

This CL never changes existing behavior.

BUG: 12981505
Change-Id: I3b2c46c47c7686b811fa248ad549f20875367425

core/java/android/view/inputmethod/InputMethodInfo.java
core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
core/tests/inputmethodtests/run_core_inputmethod_test.sh
core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java [new file with mode: 0644]

index f8160c8..bc2d7ec 100644 (file)
@@ -259,7 +259,7 @@ public final class InputMethodInfo implements Parcelable {
     public InputMethodInfo(String packageName, String className,
             CharSequence label, String settingsActivity) {
         this(buildDummyResolveInfo(packageName, className, label), false, settingsActivity, null,
-                0, false);
+                0, false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */);
     }
 
     /**
@@ -269,6 +269,17 @@ public final class InputMethodInfo implements Parcelable {
     public InputMethodInfo(ResolveInfo ri, boolean isAuxIme,
             String settingsActivity, List<InputMethodSubtype> subtypes, int isDefaultResId,
             boolean forceDefault) {
+        this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId,
+                forceDefault, true /* supportsSwitchingToNextInputMethod */);
+    }
+
+    /**
+     * Temporary API for creating a built-in input method for test.
+     * @hide
+     */
+    public InputMethodInfo(ResolveInfo ri, boolean isAuxIme,
+            String settingsActivity, List<InputMethodSubtype> subtypes, int isDefaultResId,
+            boolean forceDefault, boolean supportsSwitchingToNextInputMethod) {
         final ServiceInfo si = ri.serviceInfo;
         mService = ri;
         mId = new ComponentName(si.packageName, si.name).flattenToShortString();
@@ -277,7 +288,7 @@ public final class InputMethodInfo implements Parcelable {
         mIsAuxIme = isAuxIme;
         mSubtypes = new InputMethodSubtypeArray(subtypes);
         mForceDefault = forceDefault;
-        mSupportsSwitchingToNextInputMethod = true;
+        mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
     }
 
     private static ResolveInfo buildDummyResolveInfo(String packageName, String className,
index dcc0a4c..cba09d1 100644 (file)
@@ -16,6 +16,7 @@
 
 package com.android.internal.inputmethod;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings;
 
 import android.content.Context;
@@ -119,14 +120,14 @@ public class InputMethodSubtypeSwitchingController {
         }
     }
 
-    private static class InputMethodAndSubtypeCircularList {
+    private static class InputMethodAndSubtypeList {
         private final Context mContext;
         // Used to load label
         private final PackageManager mPm;
         private final String mSystemLocaleStr;
         private final InputMethodSettings mSettings;
 
-        public InputMethodAndSubtypeCircularList(Context context, InputMethodSettings settings) {
+        public InputMethodAndSubtypeList(Context context, InputMethodSettings settings) {
             mContext = context;
             mSettings = settings;
             mPm = context.getPackageManager();
@@ -152,38 +153,6 @@ public class InputMethodSubtypeSwitchingController {
                             }
                         });
 
-        public ImeSubtypeListItem getNextInputMethod(
-                boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) {
-            if (imi == null) {
-                return null;
-            }
-            final List<ImeSubtypeListItem> imList =
-                    getSortedInputMethodAndSubtypeList();
-            if (imList.size() <= 1) {
-                return null;
-            }
-            final int N = imList.size();
-            final int currentSubtypeId =
-                    subtype != null ? InputMethodUtils.getSubtypeIdFromHashCode(imi,
-                            subtype.hashCode()) : NOT_A_SUBTYPE_ID;
-            for (int i = 0; i < N; ++i) {
-                final ImeSubtypeListItem isli = imList.get(i);
-                if (isli.mImi.equals(imi) && isli.mSubtypeId == currentSubtypeId) {
-                    if (!onlyCurrentIme) {
-                        return imList.get((i + 1) % N);
-                    }
-                    for (int j = 0; j < N - 1; ++j) {
-                        final ImeSubtypeListItem candidate = imList.get((i + j + 1) % N);
-                        if (candidate.mImi.equals(imi)) {
-                            return candidate;
-                        }
-                    }
-                    return null;
-                }
-            }
-            return null;
-        }
-
         public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList() {
             return getSortedInputMethodAndSubtypeList(true, false, false);
         }
@@ -247,7 +216,38 @@ public class InputMethodSubtypeSwitchingController {
     private final ArrayDeque<SubtypeParams> mTypedSubtypeHistory = new ArrayDeque<SubtypeParams>();
     private final Object mLock = new Object();
     private final InputMethodSettings mSettings;
-    private InputMethodAndSubtypeCircularList mSubtypeList;
+    private InputMethodAndSubtypeList mSubtypeList;
+
+    @VisibleForTesting
+    public static ImeSubtypeListItem getNextInputMethodImpl(List<ImeSubtypeListItem> imList,
+            boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) {
+        if (imi == null) {
+            return null;
+        }
+        if (imList.size() <= 1) {
+            return null;
+        }
+        final int N = imList.size();
+        final int currentSubtypeId =
+                subtype != null ? InputMethodUtils.getSubtypeIdFromHashCode(imi,
+                        subtype.hashCode()) : NOT_A_SUBTYPE_ID;
+        for (int i = 0; i < N; ++i) {
+            final ImeSubtypeListItem isli = imList.get(i);
+            if (isli.mImi.equals(imi) && isli.mSubtypeId == currentSubtypeId) {
+                if (!onlyCurrentIme) {
+                    return imList.get((i + 1) % N);
+                }
+                for (int j = 0; j < N - 1; ++j) {
+                    final ImeSubtypeListItem candidate = imList.get((i + j + 1) % N);
+                    if (candidate.mImi.equals(imi)) {
+                        return candidate;
+                    }
+                }
+                return null;
+            }
+        }
+        return null;
+    }
 
     public InputMethodSubtypeSwitchingController(InputMethodSettings settings) {
         mSettings = settings;
@@ -278,14 +278,15 @@ public class InputMethodSubtypeSwitchingController {
 
     public void resetCircularListLocked(Context context) {
         synchronized(mLock) {
-            mSubtypeList = new InputMethodAndSubtypeCircularList(context, mSettings);
+            mSubtypeList = new InputMethodAndSubtypeList(context, mSettings);
         }
     }
 
     public ImeSubtypeListItem getNextInputMethod(
             boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) {
         synchronized(mLock) {
-            return mSubtypeList.getNextInputMethod(onlyCurrentIme, imi, subtype);
+            return getNextInputMethodImpl(mSubtypeList.getSortedInputMethodAndSubtypeList(),
+                    onlyCurrentIme, imi, subtype);
         }
     }
 
index b0b119b..9029ba5 100755 (executable)
@@ -21,4 +21,4 @@ if [[ $rebuild == true ]]; then
   $COMMAND
 fi
 
-adb shell am instrument -w -e class android.os.InputMethodTest,android.os.InputMethodSubtypeArrayTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner
+adb shell am instrument -w -e class android.os.InputMethodTest,android.os.InputMethodSubtypeArrayTest,android.os.InputMethodSubtypeSwitchingControllerTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner
diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
new file mode 100644 (file)
index 0000000..6d33529
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
+
+import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
+import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTestCase {
+    final private static String DUMMY_PACKAGE_NAME = "dymmy package name";
+    final private static String DUMMY_SETTING_ACTIVITY_NAME = "";
+    final private static boolean DUMMY_IS_AUX_IME = false;
+    final private static boolean DUMMY_FORCE_DEFAULT = false;
+    final private static int DUMMY_IS_DEFAULT_RES_ID = 0;
+    final private static String SYSTEM_LOCALE = "en_US";
+
+    private static InputMethodSubtype createDummySubtype(final String locale) {
+        final InputMethodSubtypeBuilder builder = new InputMethodSubtypeBuilder();
+        return builder.setSubtypeNameResId(0)
+                .setSubtypeIconResId(0)
+                .setSubtypeLocale(locale)
+                .setIsAsciiCapable(true)
+                .build();
+    }
+
+    private static void addDummyImeSubtypeListItems(List<ImeSubtypeListItem> items,
+            String imeName, String imeLabel, List<String> subtypeLocales,
+            boolean supportsSwitchingToNextInputMethod) {
+        final ResolveInfo ri = new ResolveInfo();
+        final ServiceInfo si = new ServiceInfo();
+        final ApplicationInfo ai = new ApplicationInfo();
+        ai.packageName = DUMMY_PACKAGE_NAME;
+        ai.enabled = true;
+        si.applicationInfo = ai;
+        si.enabled = true;
+        si.packageName = DUMMY_PACKAGE_NAME;
+        si.name = imeName;
+        si.exported = true;
+        si.nonLocalizedLabel = imeLabel;
+        ri.serviceInfo = si;
+        final List<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+        for (String subtypeLocale : subtypeLocales) {
+            subtypes.add(createDummySubtype(subtypeLocale));
+        }
+        final InputMethodInfo imi = new InputMethodInfo(ri, DUMMY_IS_AUX_IME,
+                DUMMY_SETTING_ACTIVITY_NAME, subtypes, DUMMY_IS_DEFAULT_RES_ID,
+                DUMMY_FORCE_DEFAULT, supportsSwitchingToNextInputMethod);
+        for (int i = 0; i < subtypes.size(); ++i) {
+            final String subtypeLocale = subtypeLocales.get(i);
+            final InputMethodSubtype subtype = subtypes.get(i);
+            items.add(new ImeSubtypeListItem(imeName, subtypeLocale, imi, i, subtypeLocale,
+                    SYSTEM_LOCALE));
+        }
+    }
+
+    private static List<ImeSubtypeListItem> createTestData() {
+        final List<ImeSubtypeListItem> items = new ArrayList<ImeSubtypeListItem>();
+        addDummyImeSubtypeListItems(items, "switchAwareLatinIme", "switchAwareLatinIme",
+                Arrays.asList("en_US", "es_US", "fr"),
+                true /* supportsSwitchingToNextInputMethod*/);
+        addDummyImeSubtypeListItems(items, "nonSwitchAwareLatinIme", "nonSwitchAwareLatinIme",
+                Arrays.asList("en_UK", "hi"),
+                false /* supportsSwitchingToNextInputMethod*/);
+        addDummyImeSubtypeListItems(items, "switchAwareJapaneseIme", "switchAwareJapaneseIme",
+                Arrays.asList("ja_JP"),
+                true /* supportsSwitchingToNextInputMethod*/);
+        addDummyImeSubtypeListItems(items, "nonSwitchAwareJapaneseIme", "nonSwitchAwareJapaneseIme",
+                Arrays.asList("ja_JP"),
+                false /* supportsSwitchingToNextInputMethod*/);
+        return items;
+    }
+
+    @SmallTest
+    public void testGetNextInputMethodImplWithNotOnlyCurrentIme() throws Exception {
+        final List<ImeSubtypeListItem> imList = createTestData();
+
+        final boolean ONLY_CURRENT_IME = false;
+        ImeSubtypeListItem currentIme;
+        ImeSubtypeListItem nextIme;
+
+        // "switchAwareLatinIme/en_US" -> "switchAwareLatinIme/es_US"
+        currentIme = imList.get(0);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(1), nextIme);
+        // "switchAwareLatinIme/es_US" -> "switchAwareLatinIme/fr"
+        currentIme = imList.get(1);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(2), nextIme);
+        // "switchAwareLatinIme/fr" -> "nonSwitchAwareLatinIme/en_UK
+        currentIme = imList.get(2);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(3), nextIme);
+        // "nonSwitchAwareLatinIme/en_UK" -> "nonSwitchAwareLatinIme/hi"
+        currentIme = imList.get(3);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(4), nextIme);
+        // "nonSwitchAwareLatinIme/hi" -> "switchAwareJapaneseIme/ja_JP"
+        currentIme = imList.get(4);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(5), nextIme);
+        // "switchAwareJapaneseIme/ja_JP" -> "nonSwitchAwareJapaneseIme/ja_JP"
+        currentIme = imList.get(5);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(6), nextIme);
+        // "nonSwitchAwareJapaneseIme/ja_JP" -> "switchAwareLatinIme/en_US"
+        currentIme = imList.get(6);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(0), nextIme);
+    }
+
+    @SmallTest
+    public void testGetNextInputMethodImplWithOnlyCurrentIme() throws Exception {
+        final List<ImeSubtypeListItem> imList = createTestData();
+
+        final boolean ONLY_CURRENT_IME = true;
+        ImeSubtypeListItem currentIme;
+        ImeSubtypeListItem nextIme;
+
+        // "switchAwareLatinIme/en_US" -> "switchAwareLatinIme/es_US"
+        currentIme = imList.get(0);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(1), nextIme);
+        // "switchAwareLatinIme/es_US" -> "switchAwareLatinIme/fr"
+        currentIme = imList.get(1);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(2), nextIme);
+        // "switchAwareLatinIme/fr" -> "switchAwareLatinIme/en_US"
+        currentIme = imList.get(2);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(0), nextIme);
+
+        // "nonSwitchAwareLatinIme/en_UK" -> "nonSwitchAwareLatinIme/hi"
+        currentIme = imList.get(3);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(4), nextIme);
+        // "nonSwitchAwareLatinIme/hi" -> "switchAwareLatinIme/en_UK"
+        currentIme = imList.get(4);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(3), nextIme);
+
+        // "switchAwareJapaneseIme/ja_JP" -> null
+        currentIme = imList.get(5);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertNull(nextIme);
+
+        // "nonSwitchAwareJapaneseIme/ja_JP" -> null
+        currentIme = imList.get(6);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertNull(nextIme);
+    }
+ }